Anim.cpp 29 KB

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