animobj.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. /*
  2. ** Command & Conquer Renegade(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. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/animobj.cpp $*
  25. * *
  26. * Author:: Greg_h *
  27. * *
  28. * $Modtime:: 12/13/01 6:56p $*
  29. * *
  30. * $Revision:: 10 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * Animatable3DObjClass::Animatable3DObjClass -- constructor *
  35. * Animatable3DObjClass::Animatable3DObjClass -- copy constructor *
  36. * Animatable3DObjClass::~Animatable3DObjClass -- destructor *
  37. * Animatable3DObjClass::operator = -- assignment operator *
  38. * Animatable3DObjClass::Release -- Releases any anims being held by this object *
  39. * Animatable3DObjClass::Render -- Update this object for rendering *
  40. * Animatable3DObjClass::Special_Render -- "special render" function for animatables *
  41. * Animatable3DObjClass::Set_Transform -- sets the transform and marks sub-objects as dirty *
  42. * Animatable3DObjClass::Set_Position -- Sets the position and marks sub-objects as dirty *
  43. * Animatable3DObjClass::Get_Num_Bones -- returns number of bones in this object *
  44. * Animatable3DObjClass::Get_Bone_Name -- returns the name of the given bone *
  45. * Animatable3DObjClass::Get_Bone_Index -- returns the index of the given bone *
  46. * Animatable3DObjClass::Set_Animation -- set the animation state to "none" (base pose) *
  47. * Animatable3DObjClass::Set_Animation -- Set the animation state to the given anim/frame *
  48. * Animatable3DObjClass::Set_Animation -- set the animation state to a blend of two anims *
  49. * Animatable3DObjClass::Set_Animation -- Set animation state with an anim combo *
  50. * Animatable3DObjClass::Get_Bone_Transform -- return the transform for the given bone *
  51. * Animatable3DObjClass::Get_Bone_Transform -- return the transform for the given bone *
  52. * Animatable3DObjClass::Capture_Bone -- capture the specified bone (override animation) *
  53. * Animatable3DObjClass::Release_Bone -- release the specified bone (allow animation) *
  54. * Animatable3DObjClass::Is_Bone_Captured -- returns whether the specified bone is captured *
  55. * Animatable3DObjClass::Control_Bone -- sets the transform for the bone *
  56. * Animatable3DObjClass::Update_Sub_Object_Transforms -- recalculate the transforms for our *
  57. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  58. #include "animobj.h"
  59. #include "htree.h"
  60. #include "assetmgr.h"
  61. #include "hanim.h"
  62. #include "hcanim.h"
  63. #include "ww3d.h"
  64. #include "wwmemlog.h"
  65. #include "animatedsoundmgr.h"
  66. /***********************************************************************************************
  67. * Animatable3DObjClass::Animatable3DObjClass -- constructor *
  68. * *
  69. * INPUT: *
  70. * htree_name -- name of the hierarchy tree which defines the "bone" structure for this object *
  71. * *
  72. * OUTPUT: *
  73. * *
  74. * WARNINGS: *
  75. * *
  76. * HISTORY: *
  77. * 12/8/98 GTH : Created. *
  78. *=============================================================================================*/
  79. Animatable3DObjClass::Animatable3DObjClass(const char * htree_name) :
  80. IsTreeValid(0),
  81. CurMotionMode(BASE_POSE)
  82. {
  83. // Inline struct members can't be initialized in init list for some reason...
  84. ModeAnim.Motion=NULL;
  85. ModeAnim.Frame=0.0f;
  86. ModeAnim.PrevFrame=0.0f;
  87. ModeAnim.LastSyncTime=WW3D::Get_Sync_Time();
  88. ModeInterp.Motion0=NULL;
  89. ModeInterp.Motion1=NULL;
  90. ModeInterp.Frame0=0.0f;
  91. ModeInterp.PrevFrame0=0.0f;
  92. ModeInterp.PrevFrame1=0.0f;
  93. ModeInterp.Frame1=0.0f;
  94. ModeInterp.Percentage=0.0f;
  95. ModeCombo.AnimCombo=NULL;
  96. /*
  97. ** Store a pointer to the htree
  98. */
  99. if (htree_name == NULL) {
  100. HTree = NULL;
  101. } else if (htree_name[0] == 0) {
  102. HTree = new HTreeClass;
  103. HTree->Init_Default ();
  104. } else {
  105. HTreeClass * source = WW3DAssetManager::Get_Instance()->Get_HTree(htree_name);
  106. if (source != NULL) {
  107. HTree = new HTreeClass(*source);
  108. } else {
  109. WWDEBUG_SAY(("Unable to find HTree: %s\r\n",htree_name));
  110. HTree = new HTreeClass;
  111. HTree->Init_Default();
  112. }
  113. }
  114. }
  115. /***********************************************************************************************
  116. * Animatable3DObjClass::Animatable3DObjClass -- copy constructor *
  117. * *
  118. * INPUT: *
  119. * src -- animatable object to copy. *
  120. * *
  121. * OUTPUT: *
  122. * *
  123. * WARNINGS: *
  124. * *
  125. * HISTORY: *
  126. * 12/8/98 GTH : Created. *
  127. *=============================================================================================*/
  128. Animatable3DObjClass::Animatable3DObjClass(const Animatable3DObjClass & src) :
  129. CompositeRenderObjClass(src),
  130. IsTreeValid(0),
  131. CurMotionMode(BASE_POSE),
  132. HTree(NULL)
  133. {
  134. // Inline struct members can't be initialized in init list for some reason...
  135. ModeAnim.Motion=NULL;
  136. ModeAnim.Frame=0.0f;
  137. ModeAnim.PrevFrame=0.0f;
  138. ModeAnim.LastSyncTime=WW3D::Get_Sync_Time();
  139. ModeInterp.Motion0=NULL;
  140. ModeInterp.Motion1=NULL;
  141. ModeInterp.Frame0=0.0f;
  142. ModeInterp.PrevFrame0=0.0f;
  143. ModeInterp.PrevFrame1=0.0f;
  144. ModeInterp.Frame1=0.0f;
  145. ModeInterp.Percentage=0.0f;
  146. ModeCombo.AnimCombo=NULL;
  147. *this = src;
  148. }
  149. /***********************************************************************************************
  150. * Animatable3DObjClass::~Animatable3DObjClass -- destructor *
  151. * *
  152. * INPUT: *
  153. * *
  154. * OUTPUT: *
  155. * *
  156. * WARNINGS: *
  157. * *
  158. * HISTORY: *
  159. * 12/8/98 GTH : Created. *
  160. *=============================================================================================*/
  161. Animatable3DObjClass::~Animatable3DObjClass(void)
  162. {
  163. Release();
  164. if (HTree) {
  165. delete HTree;
  166. }
  167. }
  168. /***********************************************************************************************
  169. * Animatable3DObjClass::operator = -- assignment operator *
  170. * *
  171. * INPUT: *
  172. * *
  173. * OUTPUT: *
  174. * *
  175. * WARNINGS: *
  176. * *
  177. * HISTORY: *
  178. * 3/2/99 GTH : Created. *
  179. *=============================================================================================*/
  180. Animatable3DObjClass & Animatable3DObjClass::operator = (const Animatable3DObjClass & that)
  181. {
  182. if (&that != this) {
  183. Release();
  184. if (HTree) {
  185. delete HTree;
  186. }
  187. CompositeRenderObjClass::operator = (that);
  188. IsTreeValid = 0;
  189. CurMotionMode = BASE_POSE;
  190. ModeAnim.Motion = NULL;
  191. ModeAnim.Frame = 0.0f;
  192. ModeAnim.PrevFrame = 0.0f;
  193. ModeAnim.LastSyncTime = WW3D::Get_Sync_Time();
  194. ModeInterp.Motion0 = NULL;
  195. ModeInterp.Motion1 = NULL;
  196. ModeInterp.Frame0 = 0.0f;
  197. ModeInterp.PrevFrame0 = 0.0f;
  198. ModeInterp.PrevFrame1 = 0.0f;
  199. ModeInterp.Frame1 = 0.0f;
  200. ModeInterp.Percentage = 0.0f;
  201. ModeCombo.AnimCombo = NULL;
  202. HTree = new HTreeClass(*that.HTree);
  203. }
  204. return *this;
  205. }
  206. /***********************************************************************************************
  207. * Animatable3DObjClass::Release -- Releases any anims being held by this object *
  208. * *
  209. * INPUT: *
  210. * *
  211. * OUTPUT: *
  212. * *
  213. * WARNINGS: *
  214. * *
  215. * HISTORY: *
  216. * 12/8/98 GTH : Created. *
  217. *=============================================================================================*/
  218. void Animatable3DObjClass::Release( void )
  219. {
  220. switch (CurMotionMode) {
  221. case BASE_POSE:
  222. break;
  223. case SINGLE_ANIM:
  224. if ( ModeAnim.Motion != NULL ) {
  225. ModeAnim.Motion->Release_Ref();
  226. ModeAnim.Motion = NULL;
  227. }
  228. break;
  229. case DOUBLE_ANIM:
  230. if ( ModeInterp.Motion0 != NULL ) {
  231. ModeInterp.Motion0->Release_Ref();
  232. ModeInterp.Motion0 = NULL;
  233. }
  234. if ( ModeInterp.Motion1 != NULL ) {
  235. ModeInterp.Motion1->Release_Ref();
  236. ModeInterp.Motion1 = NULL;
  237. }
  238. break;
  239. case MULTIPLE_ANIM:
  240. break;
  241. default:
  242. break;
  243. }
  244. }
  245. /***********************************************************************************************
  246. * Animatable3DObjClass::Render -- Update this object for rendering *
  247. * *
  248. * INPUT: *
  249. * *
  250. * OUTPUT: *
  251. * *
  252. * WARNINGS: *
  253. * *
  254. * HISTORY: *
  255. * 12/8/98 GTH : Created. *
  256. *=============================================================================================*/
  257. void Animatable3DObjClass::Render(RenderInfoClass & rinfo)
  258. {
  259. if (HTree == NULL) return;
  260. if (Is_Not_Hidden_At_All() == false) {
  261. return;
  262. }
  263. if ( CurMotionMode == SINGLE_ANIM ) {
  264. if ( ModeAnim.AnimMode != ANIM_MODE_MANUAL ) {
  265. Single_Anim_Progress();
  266. }
  267. }
  268. if (!Is_Hierarchy_Valid() || Are_Sub_Object_Transforms_Dirty()) {
  269. Update_Sub_Object_Transforms();
  270. }
  271. }
  272. /***********************************************************************************************
  273. * Animatable3DObjClass::Special_Render -- "special render" function for animatables *
  274. * *
  275. * INPUT: *
  276. * *
  277. * OUTPUT: *
  278. * *
  279. * WARNINGS: *
  280. * *
  281. * HISTORY: *
  282. * 12/10/98 GTH : Created. *
  283. *=============================================================================================*/
  284. void Animatable3DObjClass::Special_Render(SpecialRenderInfoClass & rinfo)
  285. {
  286. if (HTree == NULL) return;
  287. if ( CurMotionMode == SINGLE_ANIM ) {
  288. if ( ModeAnim.AnimMode != ANIM_MODE_MANUAL ) {
  289. Single_Anim_Progress();
  290. }
  291. }
  292. if (!Is_Hierarchy_Valid()) {
  293. Update_Sub_Object_Transforms();
  294. }
  295. }
  296. /***********************************************************************************************
  297. * Animatable3DObjClass::Set_Transform -- sets the transform and marks sub-objects as dirty *
  298. * *
  299. * INPUT: *
  300. * *
  301. * OUTPUT: *
  302. * *
  303. * WARNINGS: *
  304. * *
  305. * HISTORY: *
  306. * 3/2/99 GTH : Created. *
  307. *=============================================================================================*/
  308. void Animatable3DObjClass::Set_Transform(const Matrix3D &m)
  309. {
  310. CompositeRenderObjClass::Set_Transform(m);
  311. Set_Hierarchy_Valid(false);
  312. }
  313. /***********************************************************************************************
  314. * Animatable3DObjClass::Set_Position -- Sets the position and marks sub-objects as dirty *
  315. * *
  316. * INPUT: *
  317. * *
  318. * OUTPUT: *
  319. * *
  320. * WARNINGS: *
  321. * *
  322. * HISTORY: *
  323. * 3/2/99 GTH : Created. *
  324. *=============================================================================================*/
  325. void Animatable3DObjClass::Set_Position(const Vector3 &v)
  326. {
  327. CompositeRenderObjClass::Set_Position(v);
  328. Set_Hierarchy_Valid(false);
  329. }
  330. /***********************************************************************************************
  331. * Animatable3DObjClass::Get_Num_Bones -- returns number of bones in this object *
  332. * *
  333. * INPUT: *
  334. * *
  335. * OUTPUT: *
  336. * *
  337. * WARNINGS: *
  338. * *
  339. * HISTORY: *
  340. * 3/2/99 GTH : Created. *
  341. *=============================================================================================*/
  342. int Animatable3DObjClass::Get_Num_Bones(void)
  343. {
  344. if (HTree) {
  345. return HTree->Num_Pivots();
  346. } else {
  347. return 1;
  348. }
  349. }
  350. /***********************************************************************************************
  351. * Animatable3DObjClass::Get_Bone_Name -- returns the name of the given bone *
  352. * *
  353. * INPUT: *
  354. * *
  355. * OUTPUT: *
  356. * *
  357. * WARNINGS: *
  358. * *
  359. * HISTORY: *
  360. * 3/2/99 GTH : Created. *
  361. *=============================================================================================*/
  362. const char * Animatable3DObjClass::Get_Bone_Name(int bone_index)
  363. {
  364. if (HTree) {
  365. return HTree->Get_Bone_Name(bone_index);
  366. } else {
  367. return "RootTransform";
  368. }
  369. }
  370. /***********************************************************************************************
  371. * Animatable3DObjClass::Get_Bone_Index -- returns the index of the given bone *
  372. * *
  373. * INPUT: *
  374. * *
  375. * OUTPUT: *
  376. * *
  377. * WARNINGS: *
  378. * *
  379. * HISTORY: *
  380. * 3/2/99 GTH : Created. *
  381. *=============================================================================================*/
  382. int Animatable3DObjClass::Get_Bone_Index(const char * bonename)
  383. {
  384. if (HTree) {
  385. return HTree->Get_Bone_Index(bonename);
  386. } else {
  387. return 0;
  388. }
  389. }
  390. /***********************************************************************************************
  391. * Animatable3DObjClass::Set_Animation -- set the animation state to "none" (base pose) *
  392. * *
  393. * INPUT: *
  394. * *
  395. * OUTPUT: *
  396. * *
  397. * WARNINGS: *
  398. * *
  399. * HISTORY: *
  400. * 12/8/98 GTH : Created. *
  401. *=============================================================================================*/
  402. void Animatable3DObjClass::Set_Animation(void)
  403. {
  404. Release();
  405. CurMotionMode = BASE_POSE;
  406. Set_Hierarchy_Valid(false);
  407. }
  408. /***********************************************************************************************
  409. * Animatable3DObjClass::Set_Animation -- Set the animation state to the given anim/frame *
  410. * *
  411. * INPUT: *
  412. * *
  413. * OUTPUT: *
  414. * *
  415. * WARNINGS: *
  416. * *
  417. * HISTORY: *
  418. * 12/8/98 GTH : Created. *
  419. *=============================================================================================*/
  420. void Animatable3DObjClass::Set_Animation(HAnimClass * motion, float frame, int mode)
  421. {
  422. if ( motion ) {
  423. // Add_Ref before we remove, in case it is the same one.
  424. motion->Add_Ref();
  425. Release();
  426. CurMotionMode = SINGLE_ANIM;
  427. ModeAnim.Motion = motion;
  428. ModeAnim.PrevFrame = ModeAnim.Frame;
  429. ModeAnim.Frame = frame;
  430. ModeAnim.LastSyncTime = WW3D::Get_Sync_Time();
  431. ModeAnim.AnimMode = mode;
  432. } else {
  433. CurMotionMode = BASE_POSE;
  434. Release();
  435. }
  436. Set_Hierarchy_Valid(false);
  437. }
  438. /***********************************************************************************************
  439. * Animatable3DObjClass::Set_Animation -- set the animation state to a blend of two anims *
  440. * *
  441. * INPUT: *
  442. * *
  443. * OUTPUT: *
  444. * *
  445. * WARNINGS: *
  446. * *
  447. * HISTORY: *
  448. * 12/8/98 GTH : Created. *
  449. *=============================================================================================*/
  450. void Animatable3DObjClass::Set_Animation
  451. (
  452. HAnimClass * motion0,
  453. float frame0,
  454. HAnimClass * motion1,
  455. float frame1,
  456. float percentage
  457. )
  458. {
  459. Release();
  460. CurMotionMode = DOUBLE_ANIM;
  461. ModeInterp.Motion0 = motion0;
  462. ModeInterp.Motion1 = motion1;
  463. ModeInterp.PrevFrame0 = ModeInterp.Frame0;
  464. ModeInterp.PrevFrame1 = ModeInterp.Frame1;
  465. ModeInterp.Frame0 = frame0;
  466. ModeInterp.Frame1 = frame1;
  467. ModeInterp.Percentage = percentage;
  468. Set_Hierarchy_Valid(false);
  469. if ( ModeInterp.Motion0 != NULL ) {
  470. ModeInterp.Motion0->Add_Ref();
  471. }
  472. if ( ModeInterp.Motion1 != NULL ) {
  473. ModeInterp.Motion1->Add_Ref();
  474. }
  475. }
  476. /***********************************************************************************************
  477. * Animatable3DObjClass::Set_Animation -- Set animation state with an anim combo *
  478. * *
  479. * INPUT: *
  480. * *
  481. * OUTPUT: *
  482. * *
  483. * WARNINGS: *
  484. * *
  485. * HISTORY: *
  486. * 12/8/98 GTH : Created. *
  487. *=============================================================================================*/
  488. void Animatable3DObjClass::Set_Animation
  489. (
  490. HAnimComboClass * anim_combo
  491. )
  492. {
  493. Release();
  494. CurMotionMode = MULTIPLE_ANIM;
  495. ModeCombo.AnimCombo = anim_combo;
  496. Set_Hierarchy_Valid(false);
  497. }
  498. /***********************************************************************************************
  499. * Animatable3DObjClass::Peek_Animation *
  500. * *
  501. * INPUT: *
  502. * *
  503. * OUTPUT: *
  504. * *
  505. * WARNINGS: *
  506. * *
  507. * HISTORY: *
  508. * 12/8/98 GTH : Created. *
  509. *=============================================================================================*/
  510. HAnimClass * Animatable3DObjClass::Peek_Animation( void )
  511. {
  512. if ( CurMotionMode == SINGLE_ANIM ) {
  513. return ModeAnim.Motion;
  514. } else {
  515. return NULL;
  516. }
  517. }
  518. /***********************************************************************************************
  519. * Animatable3DObjClass::Get_Bone_Transform -- return the transform for the given bone *
  520. * *
  521. * INPUT: *
  522. * *
  523. * OUTPUT: *
  524. * *
  525. * WARNINGS: *
  526. * *
  527. * HISTORY: *
  528. * 12/8/98 GTH : Created. *
  529. *=============================================================================================*/
  530. const Matrix3D & Animatable3DObjClass::Get_Bone_Transform(const char * bonename)
  531. {
  532. if (HTree) {
  533. WWASSERT(HTree);
  534. WWASSERT(bonename);
  535. int idx = HTree->Get_Bone_Index(bonename);
  536. return Get_Bone_Transform(idx);
  537. } else {
  538. return Get_Transform();
  539. }
  540. }
  541. /***********************************************************************************************
  542. * Animatable3DObjClass::Get_Bone_Transform -- return the transform for the given bone *
  543. * *
  544. * INPUT: *
  545. * *
  546. * OUTPUT: *
  547. * *
  548. * WARNINGS: *
  549. * *
  550. * HISTORY: *
  551. * 12/8/98 GTH : Created. *
  552. *=============================================================================================*/
  553. const Matrix3D & Animatable3DObjClass::Get_Bone_Transform(int boneindex)
  554. {
  555. Validate_Transform();
  556. if (HTree) {
  557. /*
  558. ** If our hierarchy isn't valid, we just need to evaluate our animation
  559. ** state.
  560. */
  561. if (!Is_Hierarchy_Valid()) {
  562. Update_Sub_Object_Transforms();
  563. }
  564. return HTree->Get_Transform(boneindex);
  565. } else {
  566. return Transform;
  567. }
  568. }
  569. /***********************************************************************************************
  570. * Animatable3DObjClass::Capture_Bone -- capture the specified bone (override animation) *
  571. * *
  572. * INPUT: *
  573. * *
  574. * OUTPUT: *
  575. * *
  576. * WARNINGS: *
  577. * *
  578. * HISTORY: *
  579. * 3/2/99 GTH : Created. *
  580. *=============================================================================================*/
  581. void Animatable3DObjClass::Capture_Bone(int boneindex)
  582. {
  583. if (HTree) {
  584. HTree->Capture_Bone(boneindex);
  585. }
  586. }
  587. /***********************************************************************************************
  588. * Animatable3DObjClass::Release_Bone -- release the specified bone (allow animation) *
  589. * *
  590. * INPUT: *
  591. * *
  592. * OUTPUT: *
  593. * *
  594. * WARNINGS: *
  595. * *
  596. * HISTORY: *
  597. * 3/2/99 GTH : Created. *
  598. *=============================================================================================*/
  599. void Animatable3DObjClass::Release_Bone(int boneindex)
  600. {
  601. if (HTree) {
  602. HTree->Release_Bone(boneindex);
  603. }
  604. }
  605. /***********************************************************************************************
  606. * Animatable3DObjClass::Is_Bone_Captured -- returns whether the specified bone is captured *
  607. * *
  608. * INPUT: *
  609. * *
  610. * OUTPUT: *
  611. * *
  612. * WARNINGS: *
  613. * *
  614. * HISTORY: *
  615. * 3/2/99 GTH : Created. *
  616. *=============================================================================================*/
  617. bool Animatable3DObjClass::Is_Bone_Captured(int boneindex) const
  618. {
  619. if (HTree) {
  620. return HTree->Is_Bone_Captured(boneindex);
  621. } else {
  622. return false;
  623. }
  624. }
  625. /***********************************************************************************************
  626. * Animatable3DObjClass::Control_Bone -- sets the transform for the bone *
  627. * *
  628. * INPUT: *
  629. * *
  630. * OUTPUT: *
  631. * *
  632. * WARNINGS: *
  633. * *
  634. * HISTORY: *
  635. * 3/2/99 GTH : Created. *
  636. *=============================================================================================*/
  637. void Animatable3DObjClass::Control_Bone(int bindex,const Matrix3D & objtm,bool world_space_translation)
  638. {
  639. #ifdef WWDEBUG
  640. for (int j=0; j<3; j++) {
  641. for (int i=0; i<4; i++) {
  642. WWASSERT(WWMath::Is_Valid_Float(objtm[j][i]));
  643. }
  644. }
  645. #endif
  646. if (HTree) {
  647. HTree->Control_Bone(bindex,objtm,world_space_translation);
  648. Set_Hierarchy_Valid(false);
  649. }
  650. }
  651. /***********************************************************************************************
  652. * Animatable3DObjClass::Update_Sub_Object_Transforms -- recalculate the transforms for our su *
  653. * *
  654. * INPUT: *
  655. * *
  656. * OUTPUT: *
  657. * *
  658. * WARNINGS: *
  659. * *
  660. * HISTORY: *
  661. * 12/8/98 GTH : Created. *
  662. *=============================================================================================*/
  663. void Animatable3DObjClass::Update_Sub_Object_Transforms(void)
  664. {
  665. /*
  666. ** The RenderObj impementation will cause our 'container'
  667. ** to update if we are not valid yet
  668. */
  669. CompositeRenderObjClass::Update_Sub_Object_Transforms();
  670. /*
  671. ** Update the transforms
  672. */
  673. switch (CurMotionMode) {
  674. case BASE_POSE:
  675. Base_Update(Transform);
  676. break;
  677. case SINGLE_ANIM:
  678. if ( ModeAnim.AnimMode != ANIM_MODE_MANUAL ) {
  679. Single_Anim_Progress();
  680. }
  681. Anim_Update(Transform,ModeAnim.Motion,ModeAnim.Frame);
  682. /*
  683. ** Play any sounds that are triggered by this frame of animation
  684. */
  685. if ( ModeAnim.Motion->Has_Embedded_Sounds() ) {
  686. ModeAnim.PrevFrame = AnimatedSoundMgrClass::Trigger_Sound(ModeAnim.Motion, ModeAnim.PrevFrame, ModeAnim.Frame, Get_Transform ());
  687. }
  688. break;
  689. case DOUBLE_ANIM:
  690. Blend_Update(Transform,ModeInterp.Motion0,ModeInterp.Frame0,
  691. ModeInterp.Motion1,ModeInterp.Frame1,ModeInterp.Percentage);
  692. /*
  693. ** Play any sounds that are triggered by this frame of animation
  694. */
  695. if ( ModeInterp.Motion0->Has_Embedded_Sounds() ) {
  696. ModeInterp.PrevFrame0 = AnimatedSoundMgrClass::Trigger_Sound(ModeInterp.Motion0, ModeInterp.PrevFrame0, ModeInterp.Frame0, Get_Transform ());
  697. }
  698. if ( ModeInterp.Motion1->Has_Embedded_Sounds() ) {
  699. ModeInterp.PrevFrame1 = AnimatedSoundMgrClass::Trigger_Sound(ModeInterp.Motion1, ModeInterp.PrevFrame1, ModeInterp.Frame1, Get_Transform ());
  700. }
  701. break;
  702. case MULTIPLE_ANIM:
  703. {
  704. Combo_Update(Transform,ModeCombo.AnimCombo);
  705. /*
  706. ** Play any sounds that are triggered by this frame of animation
  707. */
  708. int count = ModeCombo.AnimCombo->Get_Num_Anims();
  709. for (int index = 0; index < count; index ++) {
  710. HAnimClass *motion = ModeCombo.AnimCombo->Peek_Motion(index);
  711. if ( motion != NULL && motion->Has_Embedded_Sounds() ) {
  712. float prev_frame = AnimatedSoundMgrClass::Trigger_Sound(motion, ModeCombo.AnimCombo->Get_Prev_Frame(index),
  713. ModeCombo.AnimCombo->Get_Frame(index), Get_Transform ());
  714. ModeCombo.AnimCombo->Set_Prev_Frame(index, prev_frame);
  715. }
  716. }
  717. break;
  718. }
  719. default:
  720. break;
  721. }
  722. Set_Hierarchy_Valid(true);
  723. }
  724. /***********************************************************************************************
  725. * Animatable3DObjClass::Simple_Evaluate_Bone -- If the animation is 'single', evaluate the *
  726. * given pivot and return its transform. *
  727. * *
  728. * INPUT: *
  729. * *
  730. * OUTPUT: *
  731. * *
  732. * WARNINGS: *
  733. * *
  734. * HISTORY: *
  735. * 04/13/2000 PDS : Created. *
  736. *=============================================================================================*/
  737. bool Animatable3DObjClass::Simple_Evaluate_Bone(int boneindex, Matrix3D *tm) const
  738. {
  739. bool retval = false;
  740. //
  741. // Only do this for simple animations
  742. //
  743. if ( CurMotionMode == NONE ||
  744. CurMotionMode == BASE_POSE ||
  745. CurMotionMode == SINGLE_ANIM)
  746. {
  747. //
  748. // Determine which frame we should be on, then use this
  749. // information to determine the bone's transform.
  750. //
  751. float curr_frame = Compute_Current_Frame ();
  752. retval = Simple_Evaluate_Bone (boneindex, curr_frame, tm);
  753. } else {
  754. const_cast <Animatable3DObjClass *>(this)->Update_Sub_Object_Transforms();
  755. *tm = HTree->Get_Transform(boneindex);
  756. }
  757. return retval;
  758. }
  759. /***********************************************************************************************
  760. * Animatable3DObjClass::Simple_Evaluate_Bone -- If the animation is 'single', evaluate the *
  761. * given pivot and return its transform. *
  762. * *
  763. * INPUT: *
  764. * *
  765. * OUTPUT: *
  766. * *
  767. * WARNINGS: *
  768. * *
  769. * HISTORY: *
  770. * 04/13/2000 PDS : Created. *
  771. *=============================================================================================*/
  772. bool Animatable3DObjClass::Simple_Evaluate_Bone(int boneindex, float frame, Matrix3D *tm) const
  773. {
  774. bool retval = false;
  775. //
  776. // Only do this for simple animations
  777. //
  778. if (HTree != NULL) {
  779. if (CurMotionMode == SINGLE_ANIM) {
  780. retval = HTree->Simple_Evaluate_Pivot (ModeAnim.Motion, boneindex, frame, Get_Transform (), tm);
  781. } else if (CurMotionMode == NONE || CurMotionMode == BASE_POSE) {
  782. retval = HTree->Simple_Evaluate_Pivot (boneindex, Get_Transform (), tm);
  783. } else {
  784. *tm = Transform;
  785. }
  786. } else {
  787. *tm = Transform;
  788. }
  789. return retval;
  790. }
  791. /***********************************************************************************************
  792. * Animatable3DObjClass::Compute_Current_Frame -- Returns the animation frame for the next rend*
  793. * *
  794. * INPUT: *
  795. * *
  796. * OUTPUT: *
  797. * *
  798. * WARNINGS: Only works for Single and CSingle! *
  799. * *
  800. * HISTORY: *
  801. * 04/13/2000 PDS : Created. *
  802. *=============================================================================================*/
  803. float Animatable3DObjClass::Compute_Current_Frame() const
  804. {
  805. float frame = 0;
  806. switch (CurMotionMode)
  807. {
  808. case SINGLE_ANIM:
  809. {
  810. frame = ModeAnim.Frame;
  811. //
  812. // Compute the current frame based on elapsed time.
  813. //
  814. if (ModeAnim.AnimMode != ANIM_MODE_MANUAL) {
  815. float sync_time_diff = WW3D::Get_Sync_Time() - ModeAnim.LastSyncTime;
  816. frame += ModeAnim.Motion->Get_Frame_Rate() * sync_time_diff * 0.001f;
  817. //
  818. // Wrap the frame
  819. //
  820. switch (ModeAnim.AnimMode)
  821. {
  822. case ANIM_MODE_ONCE:
  823. if (frame >= ModeAnim.Motion->Get_Num_Frames() - 1) {
  824. frame = ModeAnim.Motion->Get_Num_Frames() - 1;
  825. }
  826. break;
  827. case ANIM_MODE_LOOP:
  828. if ( frame >= ModeAnim.Motion->Get_Num_Frames() - 1 ) {
  829. frame -= ModeAnim.Motion->Get_Num_Frames() - 1;
  830. }
  831. // If it is still too far out, reset
  832. if ( frame >= ModeAnim.Motion->Get_Num_Frames() - 1 ) {
  833. frame = 0;
  834. }
  835. break;
  836. }
  837. }
  838. }
  839. break;
  840. }
  841. return frame;
  842. }
  843. /***********************************************************************************************
  844. * Animatable3DObjClass::Single_Anim_Progress -- progess anims for loop and once *
  845. * *
  846. * INPUT: *
  847. * *
  848. * OUTPUT: *
  849. * *
  850. * WARNINGS: Only works for Single and CSingle *
  851. * *
  852. * HISTORY: *
  853. * 10/26/99 BMG : Created. *
  854. *=============================================================================================*/
  855. void Animatable3DObjClass::Single_Anim_Progress (void)
  856. {
  857. //
  858. // Update the current frame (only works in "SINGLE_ANIM" mode!)
  859. //
  860. if (CurMotionMode == SINGLE_ANIM) {
  861. //
  862. // Update the frame number and sync time
  863. //
  864. ModeAnim.PrevFrame = ModeAnim.Frame;
  865. ModeAnim.Frame = Compute_Current_Frame();
  866. ModeAnim.LastSyncTime = WW3D::Get_Sync_Time();
  867. //
  868. // Force the heirarchy to be recalculated
  869. //
  870. Set_Hierarchy_Valid (false);
  871. }
  872. }
  873. /***********************************************************************************************
  874. * Animatable3DObjClass::Is_Animation_Complete -- is the current animation on the last frame? *
  875. * *
  876. * INPUT: *
  877. * *
  878. * OUTPUT: *
  879. * *
  880. * WARNINGS: Only works for Single, ONCE anims *
  881. * *
  882. * HISTORY: *
  883. * 4/13/99 BMG : Created. *
  884. *=============================================================================================*/
  885. bool Animatable3DObjClass::Is_Animation_Complete( void ) const
  886. {
  887. if (CurMotionMode == SINGLE_ANIM) {
  888. if ( ModeAnim.AnimMode == ANIM_MODE_ONCE ) {
  889. return ( ModeAnim.Frame == ModeAnim.Motion->Get_Num_Frames() - 1 );
  890. }
  891. }
  892. return false;
  893. }
  894. // (gth) TESTING DYNAMICALLY SWAPPING SKELETONS!
  895. void Animatable3DObjClass::Set_HTree(HTreeClass * new_htree)
  896. {
  897. WWMEMLOG(MEM_ANIMATION);
  898. // try to ensure that the htree we're using has the same structure...
  899. WWASSERT(new_htree->Num_Pivots() == HTree->Num_Pivots());
  900. // just assign it...
  901. if (HTree != NULL) {
  902. delete HTree;
  903. }
  904. HTree = new HTreeClass(*new_htree);
  905. }
  906. // EOF - animobj.cpp