animobj.cpp 52 KB

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