hcanim.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: /Commando/Code/ww3d2/hcanim.cpp 3 6/29/01 6:41p Jani_p $ */
  19. /***********************************************************************************************
  20. *** Confidential - Westwood Studios ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Commando / G 3D Library *
  24. * *
  25. * $Archive:: /Commando/Code/ww3d2/hcanim.cpp $*
  26. * *
  27. * Author:: Greg_h *
  28. * *
  29. * $Modtime:: 6/27/01 7:50p $*
  30. * *
  31. * $Revision:: 3 $*
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * NodeMotionStruct::NodeMotionStruct -- constructor *
  36. * NodeMotionStruct::~NodeMotionStruct -- destructor *
  37. * HCompressedAnimClass::HCompressedAnimClass -- constructor *
  38. * HCompressedAnimClass::~HCompressedAnimClass -- Destructor *
  39. * HCompressedAnimClass::Free -- De-allocates all memory in use *
  40. * HCompressedAnimClass::Load -- Loads hierarchy animation from a file *
  41. * HCompressedAnimClass::read_channel -- Reads in a single channel of motion *
  42. * HCompressedAnimClass::add_channel -- Adds a motion channel to the animation *
  43. * HCompressedAnimClass::Get_Translation -- returns the translation vector for the given fram*
  44. * HCompressedAnimClass::Get_Orientation -- returns a quaternion for the orientation of the p*
  45. * HCompressedAnimClass::read_bit_channel -- read a bit channel from the file *
  46. * HCompressedAnimClass::add_bit_channel -- install a bit channel into the animation *
  47. * HCompressedAnimClass::Get_Visibility -- return visibility state for given pivot/frame *
  48. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  49. #include "hcanim.h"
  50. #include "assetmgr.h"
  51. #include "htree.h"
  52. #include "motchan.h"
  53. #include "chunkio.h"
  54. #include "w3d_file.h"
  55. #include "wwdebug.h"
  56. #include <string.h>
  57. #include <nstrdup.h>
  58. struct NodeCompressedMotionStruct
  59. {
  60. NodeCompressedMotionStruct();
  61. ~NodeCompressedMotionStruct();
  62. void SetFlavor(int flavor) {Flavor = flavor;}
  63. int Flavor;
  64. union {
  65. struct {
  66. TimeCodedMotionChannelClass * X;
  67. TimeCodedMotionChannelClass * Y;
  68. TimeCodedMotionChannelClass * Z;
  69. TimeCodedMotionChannelClass * Q;
  70. } tc;
  71. struct {
  72. AdaptiveDeltaMotionChannelClass * X;
  73. AdaptiveDeltaMotionChannelClass * Y;
  74. AdaptiveDeltaMotionChannelClass * Z;
  75. AdaptiveDeltaMotionChannelClass * Q;
  76. } ad;
  77. struct {
  78. void * X;
  79. void * Y;
  80. void * Z;
  81. void * Q;
  82. } vd;
  83. };
  84. TimeCodedBitChannelClass * Vis;
  85. };
  86. /***********************************************************************************************
  87. * NodeCompressedMotionStruct::NodeCompressedMotionStruct -- constructor *
  88. * *
  89. * INPUT: *
  90. * *
  91. * OUTPUT: *
  92. * *
  93. * WARNINGS: *
  94. * *
  95. * HISTORY: *
  96. *=============================================================================================*/
  97. NodeCompressedMotionStruct::NodeCompressedMotionStruct() :
  98. Vis(NULL)
  99. {
  100. vd.X = NULL;
  101. vd.Y = NULL;
  102. vd.Z = NULL;
  103. vd.Q = NULL;
  104. }
  105. /***********************************************************************************************
  106. * NodeCompressedMotionStruct::~NodeCompressedMotionStruct -- destructor *
  107. * *
  108. * INPUT: *
  109. * *
  110. * OUTPUT: *
  111. * *
  112. * WARNINGS: *
  113. * *
  114. * HISTORY: *
  115. * 10/23/98 GTH : Created. *
  116. * 02/02/00 JGA : Compressed *
  117. *=============================================================================================*/
  118. NodeCompressedMotionStruct::~NodeCompressedMotionStruct()
  119. {
  120. // Needs to be changed to call the correct destructors
  121. switch (Flavor) {
  122. case ANIM_FLAVOR_TIMECODED:
  123. if (tc.X) delete tc.X;
  124. if (tc.Y) delete tc.Y;
  125. if (tc.Z) delete tc.Z;
  126. if (tc.Q) delete tc.Q;
  127. break;
  128. case ANIM_FLAVOR_ADAPTIVE_DELTA:
  129. if (ad.X) delete ad.X;
  130. if (ad.Y) delete ad.Y;
  131. if (ad.Z) delete ad.Z;
  132. if (ad.Q) delete ad.Q;
  133. break;
  134. default:
  135. WWASSERT(0); // unknown flavor
  136. break;
  137. }
  138. if (Vis) delete Vis;
  139. } // ~NodeCompressedMotionStruct
  140. /***********************************************************************************************
  141. * HCompressedAnimClass::HCompressedAnimClass -- constructor *
  142. * *
  143. * INPUT: *
  144. * *
  145. * OUTPUT: *
  146. * *
  147. * WARNINGS: *
  148. * *
  149. * HISTORY: *
  150. * 08/11/1997 GH : Created. *
  151. *=============================================================================================*/
  152. HCompressedAnimClass::HCompressedAnimClass(void) :
  153. NumFrames(0),
  154. NumNodes(0),
  155. Flavor(0),
  156. FrameRate(0),
  157. NodeMotion(NULL)
  158. {
  159. memset(Name,0,W3D_NAME_LEN);
  160. memset(HierarchyName,0,W3D_NAME_LEN);
  161. }
  162. /***********************************************************************************************
  163. * HCompressedAnimClass::~HCompressedAnimClass -- Destructor *
  164. * *
  165. * INPUT: *
  166. * *
  167. * OUTPUT: *
  168. * *
  169. * WARNINGS: *
  170. * *
  171. * HISTORY: *
  172. * 08/11/1997 GH : Created. *
  173. *=============================================================================================*/
  174. HCompressedAnimClass::~HCompressedAnimClass(void)
  175. {
  176. Free();
  177. }
  178. /***********************************************************************************************
  179. * HCompressedAnimClass::Free -- De-allocates all memory in use *
  180. * *
  181. * INPUT: *
  182. * *
  183. * OUTPUT: *
  184. * *
  185. * WARNINGS: *
  186. * *
  187. * HISTORY: *
  188. * 08/11/1997 GH : Created. *
  189. *=============================================================================================*/
  190. void HCompressedAnimClass::Free(void)
  191. {
  192. if (NodeMotion != NULL) {
  193. delete[] NodeMotion;
  194. }
  195. }
  196. /***********************************************************************************************
  197. * HCompressedAnimClass::Load -- Loads hierarchy animation from a file *
  198. * *
  199. * INPUT: *
  200. * *
  201. * OUTPUT: *
  202. * *
  203. * WARNINGS: *
  204. * *
  205. * HISTORY: *
  206. * 08/11/1997 GH : Created. *
  207. *=============================================================================================*/
  208. int HCompressedAnimClass::Load_W3D(ChunkLoadClass & cload)
  209. {
  210. int i = 0;
  211. /*
  212. ** First make sure we release any memory in use
  213. */
  214. Free();
  215. /*
  216. ** Open the first chunk, it should be the animation header
  217. */
  218. if (!cload.Open_Chunk()) return LOAD_ERROR;
  219. if (cload.Cur_Chunk_ID() != W3D_CHUNK_COMPRESSED_ANIMATION_HEADER) {
  220. // ERROR: Expected Animation Header!
  221. return LOAD_ERROR;
  222. }
  223. W3dCompressedAnimHeaderStruct aheader;
  224. if (cload.Read(&aheader,sizeof(W3dAnimHeaderStruct)) != sizeof(W3dAnimHeaderStruct)) {
  225. return LOAD_ERROR;
  226. }
  227. cload.Close_Chunk();
  228. strcpy(Name,aheader.HierarchyName);
  229. strcat(Name,".");
  230. strcat(Name,aheader.Name);
  231. // TSS chasing crash bug 05/26/99
  232. WWASSERT(HierarchyName != NULL);
  233. WWASSERT(aheader.HierarchyName != NULL);
  234. WWASSERT(sizeof(HierarchyName) >= W3D_NAME_LEN);
  235. strncpy(HierarchyName,aheader.HierarchyName,W3D_NAME_LEN);
  236. HTreeClass * base_pose = WW3DAssetManager::Get_Instance()->Get_HTree(HierarchyName);
  237. if (base_pose == NULL) {
  238. goto Error;
  239. }
  240. NumNodes = base_pose->Num_Pivots();
  241. NumFrames = aheader.NumFrames;
  242. FrameRate = aheader.FrameRate;
  243. Flavor = aheader.Flavor;
  244. // Just for now
  245. WWASSERT((Flavor == ANIM_FLAVOR_TIMECODED)||(Flavor == ANIM_FLAVOR_ADAPTIVE_DELTA));
  246. NodeMotion = W3DNEWARRAY NodeCompressedMotionStruct[ NumNodes ];
  247. if (NodeMotion == NULL) {
  248. goto Error;
  249. }
  250. // Initialize Flavor
  251. for (i=0; i<NumNodes; i++) {
  252. NodeMotion[i].SetFlavor(Flavor);
  253. }
  254. /*
  255. ** Now, read in all of the other chunks (motion channels).
  256. */
  257. TimeCodedMotionChannelClass * tc_chan;
  258. AdaptiveDeltaMotionChannelClass * ad_chan;
  259. TimeCodedBitChannelClass * newbitchan;
  260. while (cload.Open_Chunk()) {
  261. switch (cload.Cur_Chunk_ID()) {
  262. case W3D_CHUNK_COMPRESSED_ANIMATION_CHANNEL:
  263. switch ( Flavor ) {
  264. case ANIM_FLAVOR_TIMECODED:
  265. if (!read_channel(cload,&tc_chan)) {
  266. goto Error;
  267. }
  268. if (tc_chan->Get_Pivot() < NumNodes) {
  269. add_channel(tc_chan);
  270. } else {
  271. // PWG 12-14-98: we have only allocated space for NumNode pivots.
  272. // If we have an index thats equal or higher than NumNode we are
  273. // gonna trash memory. Boy will we trash memory.
  274. // GTH 09-25-2000: print a warning and survive this error
  275. delete tc_chan;
  276. WWDEBUG_SAY(("ERROR! animation %s indexes a bone not present in the model. Please re-export!\r\n",Name));
  277. }
  278. break;
  279. case ANIM_FLAVOR_ADAPTIVE_DELTA:
  280. if (!read_channel(cload,&ad_chan)) {
  281. goto Error;
  282. }
  283. if (ad_chan->Get_Pivot() < NumNodes) {
  284. add_channel(ad_chan);
  285. } else {
  286. // PWG 12-14-98: we have only allocated space for NumNode pivots.
  287. // If we have an index thats equal or higher than NumNode we are
  288. // gonna trash memory. Boy will we trash memory.
  289. // GTH 09-25-2000: print a warning and survive this error
  290. delete ad_chan;
  291. WWDEBUG_SAY(("ERROR! animation %s indexes a bone not present in the model. Please re-export!\r\n",Name));
  292. }
  293. break;
  294. }
  295. break;
  296. case W3D_CHUNK_COMPRESSED_BIT_CHANNEL:
  297. if (!read_bit_channel(cload,&newbitchan)) {
  298. goto Error;
  299. }
  300. if (newbitchan->Get_Pivot() < NumNodes) {
  301. add_bit_channel(newbitchan);
  302. } else {
  303. // PWG 12-14-98: we have only allocated space for NumNode pivots.
  304. // If we have an index thats equal or higher than NumNode we are
  305. // gonna trash memory. Boy will we trash memory.
  306. // GTH 09-25-2000: print a warning and survive this error
  307. delete newbitchan;
  308. WWDEBUG_SAY(("ERROR! animation %s indexes a bone not present in the model. Please re-export!\r\n",Name));
  309. }
  310. break;
  311. default:
  312. break;
  313. }
  314. cload.Close_Chunk();
  315. }
  316. return OK;
  317. Error:
  318. Free();
  319. return LOAD_ERROR;
  320. } // Load_W3D
  321. /***********************************************************************************************
  322. * HCompressedAnimClass::read_channel -- Reads in a single channel of motion *
  323. * *
  324. * INPUT: *
  325. * *
  326. * OUTPUT: *
  327. * *
  328. * WARNINGS: *
  329. * *
  330. * HISTORY: *
  331. * 08/11/1997 GH : Created. *
  332. *=============================================================================================*/
  333. bool HCompressedAnimClass::read_channel(ChunkLoadClass & cload,TimeCodedMotionChannelClass * * newchan)
  334. {
  335. *newchan = W3DNEW TimeCodedMotionChannelClass;
  336. bool result = (*newchan)->Load_W3D(cload);
  337. return result;
  338. } // read_channel
  339. bool HCompressedAnimClass::read_channel(ChunkLoadClass & cload,AdaptiveDeltaMotionChannelClass * * newchan)
  340. {
  341. *newchan = W3DNEW AdaptiveDeltaMotionChannelClass;
  342. bool result = (*newchan)->Load_W3D(cload);
  343. return result;
  344. } // read_channel
  345. /***********************************************************************************************
  346. * HCompressedAnimClass::add_channel -- Adds a motion channel to the animation *
  347. * *
  348. * INPUT: *
  349. * *
  350. * OUTPUT: *
  351. * *
  352. * WARNINGS: *
  353. * *
  354. * HISTORY: *
  355. * 08/11/1997 GH : Created. *
  356. *=============================================================================================*/
  357. void HCompressedAnimClass::add_channel(TimeCodedMotionChannelClass * newchan)
  358. {
  359. int idx = newchan->Get_Pivot();
  360. switch (newchan->Get_Type())
  361. {
  362. case ANIM_CHANNEL_X:
  363. NodeMotion[idx].tc.X = newchan;
  364. break;
  365. case ANIM_CHANNEL_Y:
  366. NodeMotion[idx].tc.Y = newchan;
  367. break;
  368. case ANIM_CHANNEL_Z:
  369. NodeMotion[idx].tc.Z = newchan;
  370. break;
  371. case ANIM_CHANNEL_Q:
  372. NodeMotion[idx].tc.Q = newchan;
  373. break;
  374. }
  375. } // add_channel
  376. void HCompressedAnimClass::add_channel(AdaptiveDeltaMotionChannelClass * newchan)
  377. {
  378. int idx = newchan->Get_Pivot();
  379. switch (newchan->Get_Type())
  380. {
  381. case ANIM_CHANNEL_X:
  382. NodeMotion[idx].ad.X = newchan;
  383. break;
  384. case ANIM_CHANNEL_Y:
  385. NodeMotion[idx].ad.Y = newchan;
  386. break;
  387. case ANIM_CHANNEL_Z:
  388. NodeMotion[idx].ad.Z = newchan;
  389. break;
  390. case ANIM_CHANNEL_Q:
  391. NodeMotion[idx].ad.Q = newchan;
  392. break;
  393. }
  394. } // add_channel
  395. /***********************************************************************************************
  396. * HCompressedAnimClass::read_bit_channel -- read a bit channel from the file *
  397. * *
  398. * INPUT: *
  399. * *
  400. * OUTPUT: *
  401. * *
  402. * WARNINGS: *
  403. * *
  404. * HISTORY: *
  405. * 1/19/98 GTH : Created. *
  406. *=============================================================================================*/
  407. bool HCompressedAnimClass::read_bit_channel(ChunkLoadClass & cload,TimeCodedBitChannelClass * * newchan)
  408. {
  409. *newchan = W3DNEW TimeCodedBitChannelClass;
  410. bool result = (*newchan)->Load_W3D(cload);
  411. return result;
  412. } // read_bit_channel
  413. /***********************************************************************************************
  414. * HCompressedAnimClass::add_bit_channel -- install a bit channel into the animation *
  415. * *
  416. * INPUT: *
  417. * *
  418. * OUTPUT: *
  419. * *
  420. * WARNINGS: *
  421. * *
  422. * HISTORY: *
  423. * 1/19/98 GTH : Created. *
  424. *=============================================================================================*/
  425. void HCompressedAnimClass::add_bit_channel(TimeCodedBitChannelClass * newchan)
  426. {
  427. int idx = newchan->Get_Pivot();
  428. switch (newchan->Get_Type())
  429. {
  430. case BIT_CHANNEL_VIS:
  431. NodeMotion[idx].Vis = newchan;
  432. break;
  433. }
  434. }
  435. /***********************************************************************************************
  436. * HCompressedAnimClass::Get_Translation -- returns the translation vector for the given frame *
  437. * *
  438. * INPUT: *
  439. * *
  440. * OUTPUT: *
  441. * *
  442. * WARNINGS: *
  443. * *
  444. * HISTORY: *
  445. * 08/11/1997 GH : Created. *
  446. *=============================================================================================*/
  447. void HCompressedAnimClass::Get_Translation( Vector3& trans, int pividx, float frame ) const
  448. {
  449. struct NodeCompressedMotionStruct * motion = &NodeMotion[pividx];
  450. trans=Vector3(0,0,0);
  451. switch(Flavor) {
  452. case ANIM_FLAVOR_TIMECODED:
  453. if (motion->tc.X) motion->tc.X->Get_Vector(frame, &(trans[0]));
  454. if (motion->tc.Y) motion->tc.Y->Get_Vector(frame, &(trans[1]));
  455. if (motion->tc.Z) motion->tc.Z->Get_Vector(frame, &(trans[2]));
  456. break;
  457. case ANIM_FLAVOR_ADAPTIVE_DELTA:
  458. if (motion->ad.X) motion->ad.X->Get_Vector(frame, &(trans[0]));
  459. if (motion->ad.Y) motion->ad.Y->Get_Vector(frame, &(trans[1]));
  460. if (motion->ad.Z) motion->ad.Z->Get_Vector(frame, &(trans[2]));
  461. break;
  462. default:
  463. WWASSERT(0); // unknown flavor
  464. break;
  465. }
  466. }
  467. /***********************************************************************************************
  468. * HCompressedAnimClass::Get_Orientation -- returns a quaternion for the orientation of the *
  469. * *
  470. * INPUT: *
  471. * *
  472. * OUTPUT: *
  473. * *
  474. * WARNINGS: *
  475. * *
  476. * HISTORY: *
  477. * 08/11/1997 GH : Created. *
  478. *=============================================================================================*/
  479. void HCompressedAnimClass::Get_Orientation(Quaternion& q, int pividx,float frame) const
  480. {
  481. switch(Flavor) {
  482. case ANIM_FLAVOR_TIMECODED:
  483. if (NodeMotion[pividx].tc.Q) q = NodeMotion[pividx].tc.Q->Get_QuatVector(frame);
  484. else q.Make_Identity();
  485. break;
  486. case ANIM_FLAVOR_ADAPTIVE_DELTA:
  487. if (NodeMotion[pividx].ad.Q) q = NodeMotion[pividx].ad.Q->Get_QuatVector(frame);
  488. else q.Make_Identity();
  489. break;
  490. default:
  491. WWASSERT(0); // unknown flavor
  492. break;
  493. }
  494. } // Get_Orientation
  495. /***********************************************************************************************
  496. * HCompressedAnimClass::Get_Transform -- returns the transform matrix for the given frame *
  497. * *
  498. * INPUT: *
  499. * *
  500. * OUTPUT: *
  501. * *
  502. * WARNINGS: *
  503. * *
  504. * HISTORY: *
  505. * 08/11/1997 GH : Created. *
  506. *=============================================================================================*/
  507. void HCompressedAnimClass::Get_Transform( Matrix3D& mtx, int pividx, float frame ) const
  508. {
  509. struct NodeCompressedMotionStruct * motion = &NodeMotion[pividx];
  510. switch(Flavor) {
  511. case ANIM_FLAVOR_TIMECODED:
  512. if (NodeMotion[pividx].tc.Q) {
  513. Quaternion q;
  514. q = NodeMotion[pividx].tc.Q->Get_QuatVector(frame);
  515. ::Build_Matrix3D(q,mtx);
  516. }
  517. else mtx.Make_Identity();
  518. if (motion->tc.X) motion->tc.X->Get_Vector(frame, &(mtx[0][3]));
  519. if (motion->tc.Y) motion->tc.Y->Get_Vector(frame, &(mtx[1][3]));
  520. if (motion->tc.Z) motion->tc.Z->Get_Vector(frame, &(mtx[2][3]));
  521. break;
  522. case ANIM_FLAVOR_ADAPTIVE_DELTA:
  523. if (NodeMotion[pividx].ad.Q) {
  524. Quaternion q;
  525. q = NodeMotion[pividx].ad.Q->Get_QuatVector(frame);
  526. ::Build_Matrix3D(q,mtx);
  527. }
  528. else mtx.Make_Identity();
  529. if (motion->ad.X) motion->ad.X->Get_Vector(frame, &(mtx[0][3]));
  530. if (motion->ad.Y) motion->ad.Y->Get_Vector(frame, &(mtx[1][3]));
  531. if (motion->ad.Z) motion->ad.Z->Get_Vector(frame, &(mtx[2][3]));
  532. break;
  533. default:
  534. WWASSERT(0); // unknown flavor
  535. break;
  536. }
  537. }
  538. /***********************************************************************************************
  539. * HCompressedAnimClass::Get_Visibility -- return visibility state for given pivot/frame *
  540. * *
  541. * INPUT: *
  542. * *
  543. * OUTPUT: *
  544. * *
  545. * WARNINGS: *
  546. * *
  547. * HISTORY: *
  548. * 1/19/98 GTH : Created. *
  549. *=============================================================================================*/
  550. bool HCompressedAnimClass::Get_Visibility(int pividx,float frame)
  551. {
  552. if (NodeMotion[pividx].Vis != NULL) {
  553. return (NodeMotion[pividx].Vis->Get_Bit((int)frame) == 1);
  554. }
  555. // default to always visible...
  556. return 1;
  557. }
  558. /***********************************************************************************************
  559. * HAnimClass::Is_Node_Motion_Present -- return true if there is motion defined for this frame *
  560. * *
  561. * INPUT: *
  562. * *
  563. * OUTPUT: *
  564. * *
  565. * WARNINGS: *
  566. * *
  567. * HISTORY: *
  568. * 3/23/99 EHC : Created. *
  569. *=============================================================================================*/
  570. bool HCompressedAnimClass::Is_Node_Motion_Present(int pividx)
  571. {
  572. WWASSERT((pividx >= 0) && (pividx < NumNodes));
  573. if (NodeMotion[pividx].vd.X != NULL) return true;
  574. if (NodeMotion[pividx].vd.Y != NULL) return true;
  575. if (NodeMotion[pividx].vd.Z != NULL) return true;
  576. if (NodeMotion[pividx].vd.Q != NULL) return true;
  577. if (NodeMotion[pividx].Vis != NULL) return true;
  578. return false;
  579. }
  580. bool HCompressedAnimClass::Has_X_Translation (int pividx)
  581. {
  582. WWASSERT((pividx >= 0) && (pividx < NumNodes));
  583. return NodeMotion[pividx].vd.X != NULL;
  584. }
  585. bool HCompressedAnimClass::Has_Y_Translation (int pividx)
  586. {
  587. WWASSERT((pividx >= 0) && (pividx < NumNodes));
  588. return NodeMotion[pividx].vd.Y != NULL;
  589. }
  590. bool HCompressedAnimClass::Has_Z_Translation (int pividx)
  591. {
  592. WWASSERT((pividx >= 0) && (pividx < NumNodes));
  593. return NodeMotion[pividx].vd.Z != NULL;
  594. }
  595. bool HCompressedAnimClass::Has_Rotation (int pividx)
  596. {
  597. WWASSERT((pividx >= 0) && (pividx < NumNodes));
  598. return NodeMotion[pividx].vd.Q != NULL;
  599. }
  600. bool HCompressedAnimClass::Has_Visibility (int pividx)
  601. {
  602. WWASSERT((pividx >= 0) && (pividx < NumNodes));
  603. return NodeMotion[pividx].Vis != NULL;
  604. }
  605. // eof - hcanim.cpp