doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Anim.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "../Game_local.h"
33 
34 bool idAnimManager::forceExport = false;
35 
36 /***********************************************************************
37 
38  idMD5Anim
39 
40 ***********************************************************************/
41 
42 /*
43 ====================
44 idMD5Anim::idMD5Anim
45 ====================
46 */
48  ref_count = 0;
49  numFrames = 0;
50  numJoints = 0;
51  frameRate = 24;
52  animLength = 0;
53  totaldelta.Zero();
54 }
55 
56 /*
57 ====================
58 idMD5Anim::idMD5Anim
59 ====================
60 */
62  Free();
63 }
64 
65 /*
66 ====================
67 idMD5Anim::Free
68 ====================
69 */
70 void idMD5Anim::Free( void ) {
71  numFrames = 0;
72  numJoints = 0;
73  frameRate = 24;
74  animLength = 0;
75  name = "";
76 
77  totaldelta.Zero();
78 
79  jointInfo.Clear();
80  bounds.Clear();
82 }
83 
84 /*
85 ====================
86 idMD5Anim::NumFrames
87 ====================
88 */
89 int idMD5Anim::NumFrames( void ) const {
90  return numFrames;
91 }
92 
93 /*
94 ====================
95 idMD5Anim::NumJoints
96 ====================
97 */
98 int idMD5Anim::NumJoints( void ) const {
99  return numJoints;
100 }
101 
102 /*
103 ====================
104 idMD5Anim::Length
105 ====================
106 */
107 int idMD5Anim::Length( void ) const {
108  return animLength;
109 }
110 
111 /*
112 =====================
113 idMD5Anim::TotalMovementDelta
114 =====================
115 */
116 const idVec3 &idMD5Anim::TotalMovementDelta( void ) const {
117  return totaldelta;
118 }
119 
120 /*
121 =====================
122 idMD5Anim::TotalMovementDelta
123 =====================
124 */
125 const char *idMD5Anim::Name( void ) const {
126  return name;
127 }
128 
129 /*
130 ====================
131 idMD5Anim::Reload
132 ====================
133 */
134 bool idMD5Anim::Reload( void ) {
135  idStr filename;
136 
137  filename = name;
138  Free();
139 
140  return LoadAnim( filename );
141 }
142 
143 /*
144 ====================
145 idMD5Anim::Allocated
146 ====================
147 */
148 size_t idMD5Anim::Allocated( void ) const {
149  size_t size = bounds.Allocated() + jointInfo.Allocated() + componentFrames.Allocated() + name.Allocated();
150  return size;
151 }
152 
153 /*
154 ====================
155 idMD5Anim::LoadAnim
156 ====================
157 */
158 bool idMD5Anim::LoadAnim( const char *filename ) {
159  int version;
161  idToken token;
162  int i, j;
163  int num;
164 
165  if ( !parser.LoadFile( filename ) ) {
166  return false;
167  }
168 
169  Free();
170 
171  name = filename;
172 
174  version = parser.ParseInt();
175  if ( version != MD5_VERSION ) {
176  parser.Error( "Invalid version %d. Should be version %d\n", version, MD5_VERSION );
177  }
178 
179  // skip the commandline
180  parser.ExpectTokenString( "commandline" );
181  parser.ReadToken( &token );
182 
183  // parse num frames
184  parser.ExpectTokenString( "numFrames" );
185  numFrames = parser.ParseInt();
186  if ( numFrames <= 0 ) {
187  parser.Error( "Invalid number of frames: %d", numFrames );
188  }
189 
190  // parse num joints
191  parser.ExpectTokenString( "numJoints" );
192  numJoints = parser.ParseInt();
193  if ( numJoints <= 0 ) {
194  parser.Error( "Invalid number of joints: %d", numJoints );
195  }
196 
197  // parse frame rate
198  parser.ExpectTokenString( "frameRate" );
199  frameRate = parser.ParseInt();
200  if ( frameRate < 0 ) {
201  parser.Error( "Invalid frame rate: %d", frameRate );
202  }
203 
204  // parse number of animated components
205  parser.ExpectTokenString( "numAnimatedComponents" );
206  numAnimatedComponents = parser.ParseInt();
207  if ( ( numAnimatedComponents < 0 ) || ( numAnimatedComponents > numJoints * 6 ) ) {
208  parser.Error( "Invalid number of animated components: %d", numAnimatedComponents );
209  }
210 
211  // parse the hierarchy
214  parser.ExpectTokenString( "hierarchy" );
215  parser.ExpectTokenString( "{" );
216  for( i = 0; i < numJoints; i++ ) {
217  parser.ReadToken( &token );
218  jointInfo[ i ].nameIndex = animationLib.JointIndex( token );
219 
220  // parse parent num
221  jointInfo[ i ].parentNum = parser.ParseInt();
222  if ( jointInfo[ i ].parentNum >= i ) {
223  parser.Error( "Invalid parent num: %d", jointInfo[ i ].parentNum );
224  }
225 
226  if ( ( i != 0 ) && ( jointInfo[ i ].parentNum < 0 ) ) {
227  parser.Error( "Animations may have only one root joint" );
228  }
229 
230  // parse anim bits
231  jointInfo[ i ].animBits = parser.ParseInt();
232  if ( jointInfo[ i ].animBits & ~63 ) {
233  parser.Error( "Invalid anim bits: %d", jointInfo[ i ].animBits );
234  }
235 
236  // parse first component
237  jointInfo[ i ].firstComponent = parser.ParseInt();
238  if ( ( numAnimatedComponents > 0 ) && ( ( jointInfo[ i ].firstComponent < 0 ) || ( jointInfo[ i ].firstComponent >= numAnimatedComponents ) ) ) {
239  parser.Error( "Invalid first component: %d", jointInfo[ i ].firstComponent );
240  }
241  }
242 
243  parser.ExpectTokenString( "}" );
244 
245  // parse bounds
246  parser.ExpectTokenString( "bounds" );
247  parser.ExpectTokenString( "{" );
248  bounds.SetGranularity( 1 );
250  for( i = 0; i < numFrames; i++ ) {
251  parser.Parse1DMatrix( 3, bounds[ i ][ 0 ].ToFloatPtr() );
252  parser.Parse1DMatrix( 3, bounds[ i ][ 1 ].ToFloatPtr() );
253  }
254  parser.ExpectTokenString( "}" );
255 
256  // parse base frame
258  baseFrame.SetNum( numJoints );
259  parser.ExpectTokenString( "baseframe" );
260  parser.ExpectTokenString( "{" );
261  for( i = 0; i < numJoints; i++ ) {
262  idCQuat q;
263  parser.Parse1DMatrix( 3, baseFrame[ i ].t.ToFloatPtr() );
264  parser.Parse1DMatrix( 3, q.ToFloatPtr() );//baseFrame[ i ].q.ToFloatPtr() );
265  baseFrame[ i ].q = q.ToQuat();//.w = baseFrame[ i ].q.CalcW();
266  }
267  parser.ExpectTokenString( "}" );
268 
269  // parse frames
272 
273  float *componentPtr = componentFrames.Ptr();
274  for( i = 0; i < numFrames; i++ ) {
275  parser.ExpectTokenString( "frame" );
276  num = parser.ParseInt();
277  if ( num != i ) {
278  parser.Error( "Expected frame number %d", i );
279  }
280  parser.ExpectTokenString( "{" );
281 
282  for( j = 0; j < numAnimatedComponents; j++, componentPtr++ ) {
283  *componentPtr = parser.ParseFloat();
284  }
285 
286  parser.ExpectTokenString( "}" );
287  }
288 
289  // get total move delta
290  if ( !numAnimatedComponents ) {
291  totaldelta.Zero();
292  } else {
293  componentPtr = &componentFrames[ jointInfo[ 0 ].firstComponent ];
294  if ( jointInfo[ 0 ].animBits & ANIM_TX ) {
295  for( i = 0; i < numFrames; i++ ) {
296  componentPtr[ numAnimatedComponents * i ] -= baseFrame[ 0 ].t.x;
297  }
298  totaldelta.x = componentPtr[ numAnimatedComponents * ( numFrames - 1 ) ];
299  componentPtr++;
300  } else {
301  totaldelta.x = 0.0f;
302  }
303  if ( jointInfo[ 0 ].animBits & ANIM_TY ) {
304  for( i = 0; i < numFrames; i++ ) {
305  componentPtr[ numAnimatedComponents * i ] -= baseFrame[ 0 ].t.y;
306  }
307  totaldelta.y = componentPtr[ numAnimatedComponents * ( numFrames - 1 ) ];
308  componentPtr++;
309  } else {
310  totaldelta.y = 0.0f;
311  }
312  if ( jointInfo[ 0 ].animBits & ANIM_TZ ) {
313  for( i = 0; i < numFrames; i++ ) {
314  componentPtr[ numAnimatedComponents * i ] -= baseFrame[ 0 ].t.z;
315  }
316  totaldelta.z = componentPtr[ numAnimatedComponents * ( numFrames - 1 ) ];
317  } else {
318  totaldelta.z = 0.0f;
319  }
320  }
321  baseFrame[ 0 ].t.Zero();
322 
323  // we don't count last frame because it would cause a 1 frame pause at the end
324  animLength = ( ( numFrames - 1 ) * 1000 + frameRate - 1 ) / frameRate;
325 
326  // done
327  return true;
328 }
329 
330 /*
331 ====================
332 idMD5Anim::IncreaseRefs
333 ====================
334 */
335 void idMD5Anim::IncreaseRefs( void ) const {
336  ref_count++;
337 }
338 
339 /*
340 ====================
341 idMD5Anim::DecreaseRefs
342 ====================
343 */
344 void idMD5Anim::DecreaseRefs( void ) const {
345  ref_count--;
346 }
347 
348 /*
349 ====================
350 idMD5Anim::NumRefs
351 ====================
352 */
353 int idMD5Anim::NumRefs( void ) const {
354  return ref_count;
355 }
356 
357 /*
358 ====================
359 idMD5Anim::GetFrameBlend
360 ====================
361 */
362 void idMD5Anim::GetFrameBlend( int framenum, frameBlend_t &frame ) const {
363  frame.cycleCount = 0;
364  frame.backlerp = 0.0f;
365  frame.frontlerp = 1.0f;
366 
367  // frame 1 is first frame
368  framenum--;
369  if ( framenum < 0 ) {
370  framenum = 0;
371  } else if ( framenum >= numFrames ) {
372  framenum = numFrames - 1;
373  }
374 
375  frame.frame1 = framenum;
376  frame.frame2 = framenum;
377 }
378 
379 /*
380 ====================
381 idMD5Anim::ConvertTimeToFrame
382 ====================
383 */
384 void idMD5Anim::ConvertTimeToFrame( int time, int cyclecount, frameBlend_t &frame ) const {
385  int frameTime;
386  int frameNum;
387 
388  if ( numFrames <= 1 ) {
389  frame.frame1 = 0;
390  frame.frame2 = 0;
391  frame.backlerp = 0.0f;
392  frame.frontlerp = 1.0f;
393  frame.cycleCount = 0;
394  return;
395  }
396 
397  if ( time <= 0 ) {
398  frame.frame1 = 0;
399  frame.frame2 = 1;
400  frame.backlerp = 0.0f;
401  frame.frontlerp = 1.0f;
402  frame.cycleCount = 0;
403  return;
404  }
405 
406  frameTime = time * frameRate;
407  frameNum = frameTime / 1000;
408  frame.cycleCount = frameNum / ( numFrames - 1 );
409 
410  if ( ( cyclecount > 0 ) && ( frame.cycleCount >= cyclecount ) ) {
411  frame.cycleCount = cyclecount - 1;
412  frame.frame1 = numFrames - 1;
413  frame.frame2 = frame.frame1;
414  frame.backlerp = 0.0f;
415  frame.frontlerp = 1.0f;
416  return;
417  }
418 
419  frame.frame1 = frameNum % ( numFrames - 1 );
420  frame.frame2 = frame.frame1 + 1;
421  if ( frame.frame2 >= numFrames ) {
422  frame.frame2 = 0;
423  }
424 
425  frame.backlerp = ( frameTime % 1000 ) * 0.001f;
426  frame.frontlerp = 1.0f - frame.backlerp;
427 }
428 
429 /*
430 ====================
431 idMD5Anim::GetOrigin
432 ====================
433 */
434 void idMD5Anim::GetOrigin( idVec3 &offset, int time, int cyclecount ) const {
435  frameBlend_t frame;
436 
437  offset = baseFrame[ 0 ].t;
438  if ( !( jointInfo[ 0 ].animBits & ( ANIM_TX | ANIM_TY | ANIM_TZ ) ) ) {
439  // just use the baseframe
440  return;
441  }
442 
443  ConvertTimeToFrame( time, cyclecount, frame );
444 
445  const float *componentPtr1 = &componentFrames[ numAnimatedComponents * frame.frame1 + jointInfo[ 0 ].firstComponent ];
446  const float *componentPtr2 = &componentFrames[ numAnimatedComponents * frame.frame2 + jointInfo[ 0 ].firstComponent ];
447 
448  if ( jointInfo[ 0 ].animBits & ANIM_TX ) {
449  offset.x = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
450  componentPtr1++;
451  componentPtr2++;
452  }
453 
454  if ( jointInfo[ 0 ].animBits & ANIM_TY ) {
455  offset.y = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
456  componentPtr1++;
457  componentPtr2++;
458  }
459 
460  if ( jointInfo[ 0 ].animBits & ANIM_TZ ) {
461  offset.z = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
462  }
463 
464  if ( frame.cycleCount ) {
465  offset += totaldelta * ( float )frame.cycleCount;
466  }
467 }
468 
469 /*
470 ====================
471 idMD5Anim::GetOriginRotation
472 ====================
473 */
474 void idMD5Anim::GetOriginRotation( idQuat &rotation, int time, int cyclecount ) const {
475  frameBlend_t frame;
476  int animBits;
477 
478  animBits = jointInfo[ 0 ].animBits;
479  if ( !( animBits & ( ANIM_QX | ANIM_QY | ANIM_QZ ) ) ) {
480  // just use the baseframe
481  rotation = baseFrame[ 0 ].q;
482  return;
483  }
484 
485  ConvertTimeToFrame( time, cyclecount, frame );
486 
487  const float *jointframe1 = &componentFrames[ numAnimatedComponents * frame.frame1 + jointInfo[ 0 ].firstComponent ];
488  const float *jointframe2 = &componentFrames[ numAnimatedComponents * frame.frame2 + jointInfo[ 0 ].firstComponent ];
489 
490  if ( animBits & ANIM_TX ) {
491  jointframe1++;
492  jointframe2++;
493  }
494 
495  if ( animBits & ANIM_TY ) {
496  jointframe1++;
497  jointframe2++;
498  }
499 
500  if ( animBits & ANIM_TZ ) {
501  jointframe1++;
502  jointframe2++;
503  }
504 
505  idQuat q1;
506  idQuat q2;
507 
508  switch( animBits & (ANIM_QX|ANIM_QY|ANIM_QZ) ) {
509  case ANIM_QX:
510  q1.x = jointframe1[0];
511  q2.x = jointframe2[0];
512  q1.y = baseFrame[ 0 ].q.y;
513  q2.y = q1.y;
514  q1.z = baseFrame[ 0 ].q.z;
515  q2.z = q1.z;
516  q1.w = q1.CalcW();
517  q2.w = q2.CalcW();
518  break;
519  case ANIM_QY:
520  q1.y = jointframe1[0];
521  q2.y = jointframe2[0];
522  q1.x = baseFrame[ 0 ].q.x;
523  q2.x = q1.x;
524  q1.z = baseFrame[ 0 ].q.z;
525  q2.z = q1.z;
526  q1.w = q1.CalcW();
527  q2.w = q2.CalcW();
528  break;
529  case ANIM_QZ:
530  q1.z = jointframe1[0];
531  q2.z = jointframe2[0];
532  q1.x = baseFrame[ 0 ].q.x;
533  q2.x = q1.x;
534  q1.y = baseFrame[ 0 ].q.y;
535  q2.y = q1.y;
536  q1.w = q1.CalcW();
537  q2.w = q2.CalcW();
538  break;
539  case ANIM_QX|ANIM_QY:
540  q1.x = jointframe1[0];
541  q1.y = jointframe1[1];
542  q2.x = jointframe2[0];
543  q2.y = jointframe2[1];
544  q1.z = baseFrame[ 0 ].q.z;
545  q2.z = q1.z;
546  q1.w = q1.CalcW();
547  q2.w = q2.CalcW();
548  break;
549  case ANIM_QX|ANIM_QZ:
550  q1.x = jointframe1[0];
551  q1.z = jointframe1[1];
552  q2.x = jointframe2[0];
553  q2.z = jointframe2[1];
554  q1.y = baseFrame[ 0 ].q.y;
555  q2.y = q1.y;
556  q1.w = q1.CalcW();
557  q2.w = q2.CalcW();
558  break;
559  case ANIM_QY|ANIM_QZ:
560  q1.y = jointframe1[0];
561  q1.z = jointframe1[1];
562  q2.y = jointframe2[0];
563  q2.z = jointframe2[1];
564  q1.x = baseFrame[ 0 ].q.x;
565  q2.x = q1.x;
566  q1.w = q1.CalcW();
567  q2.w = q2.CalcW();
568  break;
569  case ANIM_QX|ANIM_QY|ANIM_QZ:
570  q1.x = jointframe1[0];
571  q1.y = jointframe1[1];
572  q1.z = jointframe1[2];
573  q2.x = jointframe2[0];
574  q2.y = jointframe2[1];
575  q2.z = jointframe2[2];
576  q1.w = q1.CalcW();
577  q2.w = q2.CalcW();
578  break;
579  }
580 
581  rotation.Slerp( q1, q2, frame.backlerp );
582 }
583 
584 /*
585 ====================
586 idMD5Anim::GetBounds
587 ====================
588 */
589 void idMD5Anim::GetBounds( idBounds &bnds, int time, int cyclecount ) const {
590  frameBlend_t frame;
591  idVec3 offset;
592 
593  ConvertTimeToFrame( time, cyclecount, frame );
594 
595  bnds = bounds[ frame.frame1 ];
596  bnds.AddBounds( bounds[ frame.frame2 ] );
597 
598  // origin position
599  offset = baseFrame[ 0 ].t;
600  if ( jointInfo[ 0 ].animBits & ( ANIM_TX | ANIM_TY | ANIM_TZ ) ) {
601  const float *componentPtr1 = &componentFrames[ numAnimatedComponents * frame.frame1 + jointInfo[ 0 ].firstComponent ];
602  const float *componentPtr2 = &componentFrames[ numAnimatedComponents * frame.frame2 + jointInfo[ 0 ].firstComponent ];
603 
604  if ( jointInfo[ 0 ].animBits & ANIM_TX ) {
605  offset.x = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
606  componentPtr1++;
607  componentPtr2++;
608  }
609 
610  if ( jointInfo[ 0 ].animBits & ANIM_TY ) {
611  offset.y = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
612  componentPtr1++;
613  componentPtr2++;
614  }
615 
616  if ( jointInfo[ 0 ].animBits & ANIM_TZ ) {
617  offset.z = *componentPtr1 * frame.frontlerp + *componentPtr2 * frame.backlerp;
618  }
619  }
620 
621  bnds[ 0 ] -= offset;
622  bnds[ 1 ] -= offset;
623 }
624 
625 /*
626 ====================
627 idMD5Anim::GetInterpolatedFrame
628 ====================
629 */
630 void idMD5Anim::GetInterpolatedFrame( frameBlend_t &frame, idJointQuat *joints, const int *index, int numIndexes ) const {
631  int i, numLerpJoints;
632  const float *frame1;
633  const float *frame2;
634  const float *jointframe1;
635  const float *jointframe2;
636  const jointAnimInfo_t *infoPtr;
637  int animBits;
638  idJointQuat *blendJoints;
639  idJointQuat *jointPtr;
640  idJointQuat *blendPtr;
641  int *lerpIndex;
642 
643  // copy the baseframe
644  SIMDProcessor->Memcpy( joints, baseFrame.Ptr(), baseFrame.Num() * sizeof( baseFrame[ 0 ] ) );
645 
646  if ( !numAnimatedComponents ) {
647  // just use the base frame
648  return;
649  }
650 
651  blendJoints = (idJointQuat *)_alloca16( baseFrame.Num() * sizeof( blendPtr[ 0 ] ) );
652  lerpIndex = (int *)_alloca16( baseFrame.Num() * sizeof( lerpIndex[ 0 ] ) );
653  numLerpJoints = 0;
654 
655  frame1 = &componentFrames[ frame.frame1 * numAnimatedComponents ];
656  frame2 = &componentFrames[ frame.frame2 * numAnimatedComponents ];
657 
658  for ( i = 0; i < numIndexes; i++ ) {
659  int j = index[i];
660  jointPtr = &joints[j];
661  blendPtr = &blendJoints[j];
662  infoPtr = &jointInfo[j];
663 
664  animBits = infoPtr->animBits;
665  if ( animBits ) {
666 
667  lerpIndex[numLerpJoints++] = j;
668 
669  jointframe1 = frame1 + infoPtr->firstComponent;
670  jointframe2 = frame2 + infoPtr->firstComponent;
671 
672  switch( animBits & (ANIM_TX|ANIM_TY|ANIM_TZ) ) {
673  case 0:
674  blendPtr->t = jointPtr->t;
675  break;
676  case ANIM_TX:
677  jointPtr->t.x = jointframe1[0];
678  blendPtr->t.x = jointframe2[0];
679  blendPtr->t.y = jointPtr->t.y;
680  blendPtr->t.z = jointPtr->t.z;
681  jointframe1++;
682  jointframe2++;
683  break;
684  case ANIM_TY:
685  jointPtr->t.y = jointframe1[0];
686  blendPtr->t.y = jointframe2[0];
687  blendPtr->t.x = jointPtr->t.x;
688  blendPtr->t.z = jointPtr->t.z;
689  jointframe1++;
690  jointframe2++;
691  break;
692  case ANIM_TZ:
693  jointPtr->t.z = jointframe1[0];
694  blendPtr->t.z = jointframe2[0];
695  blendPtr->t.x = jointPtr->t.x;
696  blendPtr->t.y = jointPtr->t.y;
697  jointframe1++;
698  jointframe2++;
699  break;
700  case ANIM_TX|ANIM_TY:
701  jointPtr->t.x = jointframe1[0];
702  jointPtr->t.y = jointframe1[1];
703  blendPtr->t.x = jointframe2[0];
704  blendPtr->t.y = jointframe2[1];
705  blendPtr->t.z = jointPtr->t.z;
706  jointframe1 += 2;
707  jointframe2 += 2;
708  break;
709  case ANIM_TX|ANIM_TZ:
710  jointPtr->t.x = jointframe1[0];
711  jointPtr->t.z = jointframe1[1];
712  blendPtr->t.x = jointframe2[0];
713  blendPtr->t.z = jointframe2[1];
714  blendPtr->t.y = jointPtr->t.y;
715  jointframe1 += 2;
716  jointframe2 += 2;
717  break;
718  case ANIM_TY|ANIM_TZ:
719  jointPtr->t.y = jointframe1[0];
720  jointPtr->t.z = jointframe1[1];
721  blendPtr->t.y = jointframe2[0];
722  blendPtr->t.z = jointframe2[1];
723  blendPtr->t.x = jointPtr->t.x;
724  jointframe1 += 2;
725  jointframe2 += 2;
726  break;
727  case ANIM_TX|ANIM_TY|ANIM_TZ:
728  jointPtr->t.x = jointframe1[0];
729  jointPtr->t.y = jointframe1[1];
730  jointPtr->t.z = jointframe1[2];
731  blendPtr->t.x = jointframe2[0];
732  blendPtr->t.y = jointframe2[1];
733  blendPtr->t.z = jointframe2[2];
734  jointframe1 += 3;
735  jointframe2 += 3;
736  break;
737  }
738 
739  switch( animBits & (ANIM_QX|ANIM_QY|ANIM_QZ) ) {
740  case 0:
741  blendPtr->q = jointPtr->q;
742  break;
743  case ANIM_QX:
744  jointPtr->q.x = jointframe1[0];
745  blendPtr->q.x = jointframe2[0];
746  blendPtr->q.y = jointPtr->q.y;
747  blendPtr->q.z = jointPtr->q.z;
748  jointPtr->q.w = jointPtr->q.CalcW();
749  blendPtr->q.w = blendPtr->q.CalcW();
750  break;
751  case ANIM_QY:
752  jointPtr->q.y = jointframe1[0];
753  blendPtr->q.y = jointframe2[0];
754  blendPtr->q.x = jointPtr->q.x;
755  blendPtr->q.z = jointPtr->q.z;
756  jointPtr->q.w = jointPtr->q.CalcW();
757  blendPtr->q.w = blendPtr->q.CalcW();
758  break;
759  case ANIM_QZ:
760  jointPtr->q.z = jointframe1[0];
761  blendPtr->q.z = jointframe2[0];
762  blendPtr->q.x = jointPtr->q.x;
763  blendPtr->q.y = jointPtr->q.y;
764  jointPtr->q.w = jointPtr->q.CalcW();
765  blendPtr->q.w = blendPtr->q.CalcW();
766  break;
767  case ANIM_QX|ANIM_QY:
768  jointPtr->q.x = jointframe1[0];
769  jointPtr->q.y = jointframe1[1];
770  blendPtr->q.x = jointframe2[0];
771  blendPtr->q.y = jointframe2[1];
772  blendPtr->q.z = jointPtr->q.z;
773  jointPtr->q.w = jointPtr->q.CalcW();
774  blendPtr->q.w = blendPtr->q.CalcW();
775  break;
776  case ANIM_QX|ANIM_QZ:
777  jointPtr->q.x = jointframe1[0];
778  jointPtr->q.z = jointframe1[1];
779  blendPtr->q.x = jointframe2[0];
780  blendPtr->q.z = jointframe2[1];
781  blendPtr->q.y = jointPtr->q.y;
782  jointPtr->q.w = jointPtr->q.CalcW();
783  blendPtr->q.w = blendPtr->q.CalcW();
784  break;
785  case ANIM_QY|ANIM_QZ:
786  jointPtr->q.y = jointframe1[0];
787  jointPtr->q.z = jointframe1[1];
788  blendPtr->q.y = jointframe2[0];
789  blendPtr->q.z = jointframe2[1];
790  blendPtr->q.x = jointPtr->q.x;
791  jointPtr->q.w = jointPtr->q.CalcW();
792  blendPtr->q.w = blendPtr->q.CalcW();
793  break;
794  case ANIM_QX|ANIM_QY|ANIM_QZ:
795  jointPtr->q.x = jointframe1[0];
796  jointPtr->q.y = jointframe1[1];
797  jointPtr->q.z = jointframe1[2];
798  blendPtr->q.x = jointframe2[0];
799  blendPtr->q.y = jointframe2[1];
800  blendPtr->q.z = jointframe2[2];
801  jointPtr->q.w = jointPtr->q.CalcW();
802  blendPtr->q.w = blendPtr->q.CalcW();
803  break;
804  }
805  }
806  }
807 
808  SIMDProcessor->BlendJoints( joints, blendJoints, frame.backlerp, lerpIndex, numLerpJoints );
809 
810  if ( frame.cycleCount ) {
811  joints[ 0 ].t += totaldelta * ( float )frame.cycleCount;
812  }
813 }
814 
815 /*
816 ====================
817 idMD5Anim::GetSingleFrame
818 ====================
819 */
820 void idMD5Anim::GetSingleFrame( int framenum, idJointQuat *joints, const int *index, int numIndexes ) const {
821  int i;
822  const float *frame;
823  const float *jointframe;
824  int animBits;
825  idJointQuat *jointPtr;
826  const jointAnimInfo_t *infoPtr;
827 
828  // copy the baseframe
829  SIMDProcessor->Memcpy( joints, baseFrame.Ptr(), baseFrame.Num() * sizeof( baseFrame[ 0 ] ) );
830 
831  if ( ( framenum == 0 ) || !numAnimatedComponents ) {
832  // just use the base frame
833  return;
834  }
835 
836  frame = &componentFrames[ framenum * numAnimatedComponents ];
837 
838  for ( i = 0; i < numIndexes; i++ ) {
839  int j = index[i];
840  jointPtr = &joints[j];
841  infoPtr = &jointInfo[j];
842 
843  animBits = infoPtr->animBits;
844  if ( animBits ) {
845 
846  jointframe = frame + infoPtr->firstComponent;
847 
848  if ( animBits & (ANIM_TX|ANIM_TY|ANIM_TZ) ) {
849 
850  if ( animBits & ANIM_TX ) {
851  jointPtr->t.x = *jointframe++;
852  }
853 
854  if ( animBits & ANIM_TY ) {
855  jointPtr->t.y = *jointframe++;
856  }
857 
858  if ( animBits & ANIM_TZ ) {
859  jointPtr->t.z = *jointframe++;
860  }
861  }
862 
863  if ( animBits & (ANIM_QX|ANIM_QY|ANIM_QZ) ) {
864 
865  if ( animBits & ANIM_QX ) {
866  jointPtr->q.x = *jointframe++;
867  }
868 
869  if ( animBits & ANIM_QY ) {
870  jointPtr->q.y = *jointframe++;
871  }
872 
873  if ( animBits & ANIM_QZ ) {
874  jointPtr->q.z = *jointframe;
875  }
876 
877  jointPtr->q.w = jointPtr->q.CalcW();
878  }
879  }
880  }
881 }
882 
883 /*
884 ====================
885 idMD5Anim::CheckModelHierarchy
886 ====================
887 */
888 void idMD5Anim::CheckModelHierarchy( const idRenderModel *model ) const {
889  int i;
890  int jointNum;
891  int parent;
892 
893  if ( jointInfo.Num() != model->NumJoints() ) {
894  gameLocal.Error( "Model '%s' has different # of joints than anim '%s'", model->Name(), name.c_str() );
895  }
896 
897  const idMD5Joint *modelJoints = model->GetJoints();
898  for( i = 0; i < jointInfo.Num(); i++ ) {
899  jointNum = jointInfo[ i ].nameIndex;
900  if ( modelJoints[ i ].name != animationLib.JointName( jointNum ) ) {
901  gameLocal.Error( "Model '%s''s joint names don't match anim '%s''s", model->Name(), name.c_str() );
902  }
903  if ( modelJoints[ i ].parent ) {
904  parent = modelJoints[ i ].parent - modelJoints;
905  } else {
906  parent = -1;
907  }
908  if ( parent != jointInfo[ i ].parentNum ) {
909  gameLocal.Error( "Model '%s' has different joint hierarchy than anim '%s'", model->Name(), name.c_str() );
910  }
911  }
912 }
913 
914 /***********************************************************************
915 
916  idAnimManager
917 
918 ***********************************************************************/
919 
920 /*
921 ====================
922 idAnimManager::idAnimManager
923 ====================
924 */
926 }
927 
928 /*
929 ====================
930 idAnimManager::~idAnimManager
931 ====================
932 */
934  Shutdown();
935 }
936 
937 /*
938 ====================
939 idAnimManager::Shutdown
940 ====================
941 */
944  jointnames.Clear();
946 }
947 
948 /*
949 ====================
950 idAnimManager::GetAnim
951 ====================
952 */
954  idMD5Anim **animptrptr;
955  idMD5Anim *anim;
956 
957  // see if it has been asked for before
958  animptrptr = NULL;
959  if ( animations.Get( name, &animptrptr ) ) {
960  anim = *animptrptr;
961  } else {
962  idStr extension;
963  idStr filename = name;
964 
965  filename.ExtractFileExtension( extension );
966  if ( extension != MD5_ANIM_EXT ) {
967  return NULL;
968  }
969 
970  anim = new idMD5Anim();
971  if ( !anim->LoadAnim( filename ) ) {
972  gameLocal.Warning( "Couldn't load anim: '%s'", filename.c_str() );
973  delete anim;
974  anim = NULL;
975  }
976  animations.Set( filename, anim );
977  }
978 
979  return anim;
980 }
981 
982 /*
983 ================
984 idAnimManager::ReloadAnims
985 ================
986 */
988  int i;
989  idMD5Anim **animptr;
990 
991  for( i = 0; i < animations.Num(); i++ ) {
992  animptr = animations.GetIndex( i );
993  if ( animptr && *animptr ) {
994  ( *animptr )->Reload();
995  }
996  }
997 }
998 
999 /*
1000 ================
1001 idAnimManager::JointIndex
1002 ================
1003 */
1004 int idAnimManager::JointIndex( const char *name ) {
1005  int i, hash;
1006 
1007  hash = jointnamesHash.GenerateKey( name );
1008  for ( i = jointnamesHash.First( hash ); i != -1; i = jointnamesHash.Next( i ) ) {
1009  if ( jointnames[i].Cmp( name ) == 0 ) {
1010  return i;
1011  }
1012  }
1013 
1014  i = jointnames.Append( name );
1015  jointnamesHash.Add( hash, i );
1016  return i;
1017 }
1018 
1019 /*
1020 ================
1021 idAnimManager::JointName
1022 ================
1023 */
1024 const char *idAnimManager::JointName( int index ) const {
1025  return jointnames[ index ];
1026 }
1027 
1028 /*
1029 ================
1030 idAnimManager::ListAnims
1031 ================
1032 */
1033 void idAnimManager::ListAnims( void ) const {
1034  int i;
1035  idMD5Anim **animptr;
1036  idMD5Anim *anim;
1037  size_t size;
1038  size_t s;
1039  size_t namesize;
1040  int num;
1041 
1042  num = 0;
1043  size = 0;
1044  for( i = 0; i < animations.Num(); i++ ) {
1045  animptr = animations.GetIndex( i );
1046  if ( animptr && *animptr ) {
1047  anim = *animptr;
1048  s = anim->Size();
1049  gameLocal.Printf( "%8d bytes : %2d refs : %s\n", s, anim->NumRefs(), anim->Name() );
1050  size += s;
1051  num++;
1052  }
1053  }
1054 
1055  namesize = jointnames.Size() + jointnamesHash.Size();
1056  for( i = 0; i < jointnames.Num(); i++ ) {
1057  namesize += jointnames[ i ].Size();
1058  }
1059 
1060  gameLocal.Printf( "\n%d memory used in %d anims\n", size, num );
1061  gameLocal.Printf( "%d memory used in %d joint names\n", namesize, jointnames.Num() );
1062 }
1063 
1064 /*
1065 ================
1066 idAnimManager::FlushUnusedAnims
1067 ================
1068 */
1070  int i;
1071  idMD5Anim **animptr;
1072  idList<idMD5Anim *> removeAnims;
1073 
1074  for( i = 0; i < animations.Num(); i++ ) {
1075  animptr = animations.GetIndex( i );
1076  if ( animptr && *animptr ) {
1077  if ( ( *animptr )->NumRefs() <= 0 ) {
1078  removeAnims.Append( *animptr );
1079  }
1080  }
1081  }
1082 
1083  for( i = 0; i < removeAnims.Num(); i++ ) {
1084  animations.Remove( removeAnims[ i ]->Name() );
1085  delete removeAnims[ i ];
1086  }
1087 }
int JointIndex(const char *name)
Definition: Anim.cpp:1004
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:2959
bool AddBounds(const idBounds &a)
Definition: Bounds.h:255
#define MD5_ANIM_EXT
Definition: Model.h:43
const float * ToFloatPtr(void) const
Definition: Quat.h:396
int animLength
Definition: Anim.h:230
Definition: Quat.h:306
int Next(const int index) const
Definition: HashIndex.h:247
size_t Size(void) const
Definition: HashIndex.h:147
void Printf(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:699
void ListAnims(void) const
Definition: Anim.cpp:1033
int animBits
Definition: Anim.h:71
void SetNum(int newnum, bool resize=true)
Definition: List.h:289
#define ANIM_TY
Definition: Anim.h:101
void void void void void Error(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:783
void GetBounds(idBounds &bounds, int currentTime, int cyclecount) const
Definition: Anim.cpp:589
int Parse1DMatrix(int x, float *m)
Definition: Lexer.cpp:1300
float w
Definition: Quat.h:53
#define ANIM_QY
Definition: Anim.h:104
float z
Definition: Vector.h:320
idHashIndex jointnamesHash
Definition: Anim.h:624
void SetGranularity(int newgranularity)
Definition: List.h:305
int numFrames
Definition: Anim.h:228
#define MD5_VERSION_STRING
Definition: Model.h:41
Type * GetIndex(int index) const
Definition: HashTable.h:248
Definition: Vector.h:316
case const float
Definition: Callbacks.cpp:62
type * Ptr(void)
Definition: List.h:596
virtual const char * Name() const =0
Definition: Token.h:71
idList< idBounds > bounds
Definition: Anim.h:233
void GetOrigin(idVec3 &offset, int currentTime, int cyclecount) const
Definition: Anim.cpp:434
int frame1
Definition: Anim.h:62
float ParseFloat(bool *errorFlag=NULL)
Definition: Lexer.cpp:1264
GLdouble s
Definition: glext.h:2935
float x
Definition: Vector.h:318
#define ANIM_TX
Definition: Anim.h:100
void IncreaseRefs(void) const
Definition: Anim.cpp:335
idQuat & Slerp(const idQuat &from, const idQuat &to, float t)
Definition: Quat.cpp:160
void CheckModelHierarchy(const idRenderModel *model) const
Definition: Anim.cpp:888
int i
Definition: process.py:33
GLintptr offset
Definition: glext.h:3113
int ParseInt(void)
Definition: Lexer.cpp:1227
~idMD5Anim()
Definition: Anim.cpp:61
GLuint GLuint num
Definition: glext.h:5390
int ref_count
Definition: Anim.h:239
void Free(void)
Definition: HashIndex.cpp:75
int cycleCount
Definition: Anim.h:61
int First(const int key) const
Definition: HashIndex.h:238
float x
Definition: Quat.h:50
~idAnimManager()
Definition: Anim.cpp:933
void Shutdown(void)
Definition: Anim.cpp:942
idAnimManager()
Definition: Anim.cpp:925
void DeleteContents(void)
Definition: HashTable.h:335
void void void Warning(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:735
virtual const idMD5Joint * GetJoints(void) const =0
float y
Definition: Quat.h:51
struct version_s version
void Free(void)
Definition: Anim.cpp:70
void Set(const char *key, Type &value)
Definition: HashTable.h:186
idList< float > componentFrames
Definition: Anim.h:236
Definition: Lexer.h:137
void Error(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:215
idMD5Anim()
Definition: Anim.cpp:47
idMD5Anim * GetAnim(const char *name)
Definition: Anim.cpp:953
GLuint index
Definition: glext.h:3476
int Length(void) const
Definition: Anim.cpp:107
int numJoints
Definition: Anim.h:231
int NumRefs(void) const
Definition: Anim.cpp:353
virtual void VPCALL BlendJoints(idJointQuat *joints, const idJointQuat *blendJoints, const float lerp, const int *index, const int numJoints)=0
static bool forceExport
Definition: Anim.h:609
#define NULL
Definition: Lib.h:88
float frontlerp
Definition: Anim.h:64
const idMD5Joint * parent
Definition: Model.h:164
float y
Definition: Vector.h:319
void GetFrameBlend(int framenum, frameBlend_t &frame) const
Definition: Anim.cpp:362
size_t Size(void) const
Definition: List.h:242
const char * JointName(int index) const
Definition: Anim.cpp:1024
void GetInterpolatedFrame(frameBlend_t &frame, idJointQuat *joints, const int *index, int numIndexes) const
Definition: Anim.cpp:630
const char * Name(void) const
Definition: Anim.cpp:125
size_t Allocated(void) const
Definition: List.h:230
idList< jointAnimInfo_t > jointInfo
Definition: Anim.h:234
size_t Size(void) const
Definition: Anim.h:248
bool Remove(const char *key)
Definition: HashTable.h:277
idHashTable< idMD5Anim * > animations
Definition: Anim.h:622
idGameLocal gameLocal
Definition: Game_local.cpp:64
idVec3 totaldelta
Definition: Anim.h:238
void FlushUnusedAnims(void)
Definition: Anim.cpp:1069
int NumJoints(void) const
Definition: Anim.cpp:98
virtual void VPCALL Memcpy(void *dst, const void *src, const int count)=0
int GenerateKey(const char *string, bool caseSensitive=true) const
Definition: HashIndex.h:379
idList< idJointQuat > baseFrame
Definition: Anim.h:235
Definition: Quat.h:48
idStrList jointnames
Definition: Anim.h:623
bool Get(const char *key, Type **value=NULL) const
Definition: HashTable.h:214
int ExpectTokenString(const char *string)
Definition: Lexer.cpp:919
float z
Definition: Quat.h:52
int Num(void) const
Definition: HashTable.h:361
int Append(const type &obj)
Definition: List.h:646
float backlerp
Definition: Anim.h:65
void ReloadAnims(void)
Definition: Anim.cpp:987
bool Reload(void)
Definition: Anim.cpp:134
void DecreaseRefs(void) const
Definition: Anim.cpp:344
int firstComponent
Definition: Anim.h:72
int numAnimatedComponents
Definition: Anim.h:232
#define ANIM_TZ
Definition: Anim.h:102
tuple f
Definition: idal.py:89
int Num(void) const
Definition: List.h:265
#define ANIM_QX
Definition: Anim.h:103
const GLcharARB * name
Definition: glext.h:3629
GLsizeiptr size
Definition: glext.h:3112
idQuat ToQuat(void) const
Definition: Quat.h:391
const idVec3 & TotalMovementDelta(void) const
Definition: Anim.cpp:116
Definition: Str.h:116
idAnimManager animationLib
Definition: Game_local.cpp:61
int frame2
Definition: Anim.h:63
const char * c_str(void) const
Definition: Str.h:487
int frameRate
Definition: Anim.h:229
virtual int NumJoints(void) const =0
float CalcW(void) const
Definition: Quat.h:280
void Add(const int key, const int index)
Definition: HashIndex.h:193
void GetSingleFrame(int framenum, idJointQuat *joints, const int *index, int numIndexes) const
Definition: Anim.cpp:820
size_t Allocated(void) const
Definition: Anim.cpp:148
GLint j
Definition: qgl.h:264
void GetOriginRotation(idQuat &rotation, int time, int cyclecount) const
Definition: Anim.cpp:474
void ExtractFileExtension(idStr &dest) const
Definition: Str.cpp:965
Definition: List.h:84
#define MD5_VERSION
Definition: Model.h:45
void Zero(void)
Definition: Vector.h:415
int ReadToken(idToken *token)
Definition: Lexer.cpp:820
bool LoadAnim(const char *filename)
Definition: Anim.cpp:158
void ConvertTimeToFrame(int time, int cyclecount, frameBlend_t &frame) const
Definition: Anim.cpp:384
int LoadFile(const char *filename, bool OSPath=false)
Definition: Lexer.cpp:1591
int NumFrames(void) const
Definition: Anim.cpp:89
#define ANIM_QZ
Definition: Anim.h:105
GLdouble GLdouble t
Definition: glext.h:2943
void Clear(void)
Definition: List.h:184
idSIMDProcessor * SIMDProcessor
Definition: Simd.cpp:43
idStr name
Definition: Anim.h:237