Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
animobj.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(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/***********************************************************************************************
20 *** 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 ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WW3D *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/animobj.cpp $*
26 * *
27 * Author:: Greg_h *
28 * *
29 * $Modtime:: 12/13/01 6:56p $*
30 * *
31 * $Revision:: 10 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * Animatable3DObjClass::Animatable3DObjClass -- constructor *
36 * Animatable3DObjClass::Animatable3DObjClass -- copy constructor *
37 * Animatable3DObjClass::~Animatable3DObjClass -- destructor *
38 * Animatable3DObjClass::operator = -- assignment operator *
39 * Animatable3DObjClass::Release -- Releases any anims being held by this object *
40 * Animatable3DObjClass::Render -- Update this object for rendering *
41 * Animatable3DObjClass::Special_Render -- "special render" function for animatables *
42 * Animatable3DObjClass::Set_Transform -- sets the transform and marks sub-objects as dirty *
43 * Animatable3DObjClass::Set_Position -- Sets the position and marks sub-objects as dirty *
44 * Animatable3DObjClass::Get_Num_Bones -- returns number of bones in this object *
45 * Animatable3DObjClass::Get_Bone_Name -- returns the name of the given bone *
46 * Animatable3DObjClass::Get_Bone_Index -- returns the index of the given bone *
47 * Animatable3DObjClass::Set_Animation -- set the animation state to "none" (base pose) *
48 * Animatable3DObjClass::Set_Animation -- Set the animation state to the given anim/frame *
49 * Animatable3DObjClass::Set_Animation -- set the animation state to a blend of two anims *
50 * Animatable3DObjClass::Set_Animation -- Set animation state with an anim combo *
51 * Animatable3DObjClass::Get_Bone_Transform -- return the transform for the given bone *
52 * Animatable3DObjClass::Get_Bone_Transform -- return the transform for the given bone *
53 * Animatable3DObjClass::Capture_Bone -- capture the specified bone (override animation) *
54 * Animatable3DObjClass::Release_Bone -- release the specified bone (allow animation) *
55 * Animatable3DObjClass::Is_Bone_Captured -- returns whether the specified bone is captured *
56 * Animatable3DObjClass::Control_Bone -- sets the transform for the bone *
57 * Animatable3DObjClass::Update_Sub_Object_Transforms -- recalculate the transforms for our *
58 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
59
60
61#include "animobj.h"
62#include "htree.h"
63#include "assetmgr.h"
64#include "hanim.h"
65#include "hcanim.h"
66#include "ww3d.h"
67#include "wwmemlog.h"
68#include "animatedsoundmgr.h"
69
70
71/***********************************************************************************************
72 * Animatable3DObjClass::Animatable3DObjClass -- constructor *
73 * *
74 * INPUT: *
75 * htree_name -- name of the hierarchy tree which defines the "bone" structure for this object *
76 * *
77 * OUTPUT: *
78 * *
79 * WARNINGS: *
80 * *
81 * HISTORY: *
82 * 12/8/98 GTH : Created. *
83 *=============================================================================================*/
85 IsTreeValid(0),
87{
88 // Inline struct members can't be initialized in init list for some reason...
89 ModeAnim.Motion=NULL;
90 ModeAnim.Frame=0.0f;
91 ModeAnim.PrevFrame=0.0f;
92 ModeAnim.LastSyncTime=WW3D::Get_Sync_Time();
93 ModeAnim.frameRateMultiplier=1.0; // 020607 srj -- added
94 ModeAnim.animDirection=1.0; // 020607 srj -- added
95 ModeInterp.Motion0=NULL;
96 ModeInterp.Motion1=NULL;
97 ModeInterp.Frame0=0.0f;
98 ModeInterp.PrevFrame0=0.0f;
99 ModeInterp.PrevFrame1=0.0f;
100 ModeInterp.Frame1=0.0f;
101 ModeInterp.Percentage=0.0f;
102 ModeCombo.AnimCombo=NULL;
103
104 /*
105 ** Store a pointer to the htree
106 */
107 if (htree_name == NULL) {
108 HTree = NULL;
109 } else if (htree_name[0] == 0) {
111 HTree->Init_Default ();
112 } else {
113 HTreeClass * source = WW3DAssetManager::Get_Instance()->Get_HTree(htree_name);
114 if (source != NULL) {
115 HTree = W3DNEW HTreeClass(*source);
116 } else {
117 WWDEBUG_SAY(("Unable to find HTree: %s\r\n",htree_name));
119 HTree->Init_Default();
120 }
121 }
122}
123
124
125/***********************************************************************************************
126 * Animatable3DObjClass::Animatable3DObjClass -- copy constructor *
127 * *
128 * INPUT: *
129 * src -- animatable object to copy. *
130 * *
131 * OUTPUT: *
132 * *
133 * WARNINGS: *
134 * *
135 * HISTORY: *
136 * 12/8/98 GTH : Created. *
137 *=============================================================================================*/
140 IsTreeValid(0),
142 HTree(NULL)
143{
144 // Inline struct members can't be initialized in init list for some reason...
145 ModeAnim.Motion=NULL;
146 ModeAnim.Frame=0.0f;
147 ModeAnim.PrevFrame=0.0f;
148 ModeAnim.LastSyncTime=WW3D::Get_Sync_Time();
149 ModeAnim.frameRateMultiplier=1.0; // 020607 srj -- added
150 ModeAnim.animDirection=1.0; // 020607 srj -- added
151 ModeInterp.Motion0=NULL;
152 ModeInterp.Motion1=NULL;
153 ModeInterp.Frame0=0.0f;
154 ModeInterp.PrevFrame0=0.0f;
155 ModeInterp.PrevFrame1=0.0f;
156 ModeInterp.Frame1=0.0f;
157 ModeInterp.Percentage=0.0f;
158 ModeCombo.AnimCombo=NULL;
159
160 *this = src;
161}
162
163
164/***********************************************************************************************
165 * Animatable3DObjClass::~Animatable3DObjClass -- destructor *
166 * *
167 * INPUT: *
168 * *
169 * OUTPUT: *
170 * *
171 * WARNINGS: *
172 * *
173 * HISTORY: *
174 * 12/8/98 GTH : Created. *
175 *=============================================================================================*/
177{
178 Release();
179
180 if (HTree) {
181 delete HTree;
182 }
183}
184
185
186/***********************************************************************************************
187 * Animatable3DObjClass::operator = -- assignment operator *
188 * *
189 * INPUT: *
190 * *
191 * OUTPUT: *
192 * *
193 * WARNINGS: *
194 * *
195 * HISTORY: *
196 * 3/2/99 GTH : Created. *
197 *=============================================================================================*/
199{
200 if (&that != this) {
201 Release();
202 if (HTree) {
203 delete HTree;
204 }
205
207
208 IsTreeValid = 0;
210 ModeAnim.Motion = NULL;
211 ModeAnim.Frame = 0.0f;
212 ModeAnim.PrevFrame = 0.0f;
213 ModeAnim.LastSyncTime = WW3D::Get_Sync_Time();
214 ModeAnim.frameRateMultiplier=1.0; // 020607 srj -- added
215 ModeAnim.animDirection=1.0; // 020607 srj -- added
216 ModeInterp.Motion0 = NULL;
217 ModeInterp.Motion1 = NULL;
218 ModeInterp.Frame0 = 0.0f;
219 ModeInterp.PrevFrame0 = 0.0f;
220 ModeInterp.PrevFrame1 = 0.0f;
221 ModeInterp.Frame1 = 0.0f;
222 ModeInterp.Percentage = 0.0f;
223 ModeCombo.AnimCombo = NULL;
224
225 HTree = W3DNEW HTreeClass(*that.HTree);
226 }
227 return *this;
228}
229
230/***********************************************************************************************
231 * Animatable3DObjClass::Release -- Releases any anims being held by this object *
232 * *
233 * INPUT: *
234 * *
235 * OUTPUT: *
236 * *
237 * WARNINGS: *
238 * *
239 * HISTORY: *
240 * 12/8/98 GTH : Created. *
241 *=============================================================================================*/
243{
244 switch (CurMotionMode) {
245
246 case BASE_POSE:
247 break;
248
249 case SINGLE_ANIM:
250 if ( ModeAnim.Motion != NULL ) {
251 ModeAnim.Motion->Release_Ref();
252 ModeAnim.Motion = NULL;
253 }
254 break;
255
256 case DOUBLE_ANIM:
257 if ( ModeInterp.Motion0 != NULL ) {
258 ModeInterp.Motion0->Release_Ref();
259 ModeInterp.Motion0 = NULL;
260 }
261
262 if ( ModeInterp.Motion1 != NULL ) {
263 ModeInterp.Motion1->Release_Ref();
264 ModeInterp.Motion1 = NULL;
265 }
266 break;
267
268 case MULTIPLE_ANIM:
269 break;
270
271 default:
272 break;
273 }
274}
275
276/***********************************************************************************************
277 * Animatable3DObjClass::Render -- Update this object for rendering *
278 * *
279 * INPUT: *
280 * *
281 * OUTPUT: *
282 * *
283 * WARNINGS: *
284 * *
285 * HISTORY: *
286 * 12/8/98 GTH : Created. *
287 *=============================================================================================*/
289{
290 if (HTree == NULL) return;
291
292 if (Is_Not_Hidden_At_All() == false) {
293 return;
294 }
295
296 if ( CurMotionMode == SINGLE_ANIM ) {
297 if ( ModeAnim.AnimMode != ANIM_MODE_MANUAL ) {
299 }
300 }
301
304 }
305}
306
307/***********************************************************************************************
308 * Animatable3DObjClass::Special_Render -- "special render" function for animatables *
309 * *
310 * INPUT: *
311 * *
312 * OUTPUT: *
313 * *
314 * WARNINGS: *
315 * *
316 * HISTORY: *
317 * 12/10/98 GTH : Created. *
318 *=============================================================================================*/
320{
321 if (HTree == NULL) return;
322
323 if ( CurMotionMode == SINGLE_ANIM ) {
324 if ( ModeAnim.AnimMode != ANIM_MODE_MANUAL ) {
326 }
327 }
328
329 if (!Is_Hierarchy_Valid()) {
331 }
332}
333
334
335/***********************************************************************************************
336 * Animatable3DObjClass::Set_Transform -- sets the transform and marks sub-objects as dirty *
337 * *
338 * INPUT: *
339 * *
340 * OUTPUT: *
341 * *
342 * WARNINGS: *
343 * *
344 * HISTORY: *
345 * 3/2/99 GTH : Created. *
346 *=============================================================================================*/
352
353
354/***********************************************************************************************
355 * Animatable3DObjClass::Set_Position -- Sets the position and marks sub-objects as dirty *
356 * *
357 * INPUT: *
358 * *
359 * OUTPUT: *
360 * *
361 * WARNINGS: *
362 * *
363 * HISTORY: *
364 * 3/2/99 GTH : Created. *
365 *=============================================================================================*/
371
372
373/***********************************************************************************************
374 * Animatable3DObjClass::Get_Num_Bones -- returns number of bones in this object *
375 * *
376 * INPUT: *
377 * *
378 * OUTPUT: *
379 * *
380 * WARNINGS: *
381 * *
382 * HISTORY: *
383 * 3/2/99 GTH : Created. *
384 *=============================================================================================*/
386{
387 if (HTree) {
388 return HTree->Num_Pivots();
389 } else {
390 return 1;
391 }
392}
393
394
395/***********************************************************************************************
396 * Animatable3DObjClass::Get_Bone_Name -- returns the name of the given bone *
397 * *
398 * INPUT: *
399 * *
400 * OUTPUT: *
401 * *
402 * WARNINGS: *
403 * *
404 * HISTORY: *
405 * 3/2/99 GTH : Created. *
406 *=============================================================================================*/
407const char * Animatable3DObjClass::Get_Bone_Name(int bone_index)
408{
409 if (HTree) {
410 return HTree->Get_Bone_Name(bone_index);
411 } else {
412 return "RootTransform";
413 }
414}
415
416
417/***********************************************************************************************
418 * Animatable3DObjClass::Get_Bone_Index -- returns the index of the given bone *
419 * *
420 * INPUT: *
421 * *
422 * OUTPUT: *
423 * *
424 * WARNINGS: *
425 * *
426 * HISTORY: *
427 * 3/2/99 GTH : Created. *
428 *=============================================================================================*/
429int Animatable3DObjClass::Get_Bone_Index(const char * bonename)
430{
431 if (HTree) {
432 return HTree->Get_Bone_Index(bonename);
433 } else {
434 return 0;
435 }
436}
437
438
439
440/***********************************************************************************************
441 * Animatable3DObjClass::Set_Animation -- set the animation state to "none" (base pose) *
442 * *
443 * INPUT: *
444 * *
445 * OUTPUT: *
446 * *
447 * WARNINGS: *
448 * *
449 * HISTORY: *
450 * 12/8/98 GTH : Created. *
451 *=============================================================================================*/
458
459
460/***********************************************************************************************
461 * Animatable3DObjClass::Set_Animation -- Set the animation state to the given anim/frame *
462 * *
463 * INPUT: *
464 * *
465 * OUTPUT: *
466 * *
467 * WARNINGS: *
468 * *
469 * HISTORY: *
470 * 12/8/98 GTH : Created. *
471 *=============================================================================================*/
472void Animatable3DObjClass::Set_Animation(HAnimClass * motion, float frame, int mode)
473{
474
475 if ( motion ) {
476 // Add_Ref before we remove, in case it is the same one.
477 motion->Add_Ref();
478 Release();
480 ModeAnim.Motion = motion;
481 ModeAnim.PrevFrame = ModeAnim.Frame;
482 ModeAnim.Frame = frame;
483 ModeAnim.LastSyncTime = WW3D::Get_Sync_Time();
484 ModeAnim.frameRateMultiplier=1.0; // 020607 srj -- added
485 ModeAnim.animDirection=1.0; // 020607 srj -- added
486
487 ModeAnim.AnimMode = mode;
488
489 if (mode < ANIM_MODE_LOOP_BACKWARDS)
490 ModeAnim.animDirection = 1.0f; //assume playing forwards
491 else
492 ModeAnim.animDirection = -1.0f; //reverse animation playback
493
494 const char* sound_name = AnimatedSoundMgrClass::Get_Embedded_Sound_Name(motion);
495 if (sound_name) {
496 int bone_index = Get_Bone_Index(sound_name);
497 motion->Set_Embedded_Sound_Bone_Index(bone_index);
498 }
499 } else {
501 Release();
502 }
503
504 Set_Hierarchy_Valid(false);
505}
506
507/***********************************************************************************************
508 * Animatable3DObjClass::Set_Animation -- set the animation state to a blend of two anims *
509 * *
510 * INPUT: *
511 * *
512 * OUTPUT: *
513 * *
514 * WARNINGS: *
515 * *
516 * HISTORY: *
517 * 12/8/98 GTH : Created. *
518 *=============================================================================================*/
520(
521 HAnimClass * motion0,
522 float frame0,
523 HAnimClass * motion1,
524 float frame1,
525 float percentage
526)
527{
528 Release();
529
531 ModeInterp.Motion0 = motion0;
532 ModeInterp.Motion1 = motion1;
533 ModeInterp.PrevFrame0 = ModeInterp.Frame0;
534 ModeInterp.PrevFrame1 = ModeInterp.Frame1;
535 ModeInterp.Frame0 = frame0;
536 ModeInterp.Frame1 = frame1;
537 ModeInterp.Percentage = percentage;
538 Set_Hierarchy_Valid(false);
539
540 if ( ModeInterp.Motion0 != NULL ) {
541 ModeInterp.Motion0->Add_Ref();
542 const char* sound_name = AnimatedSoundMgrClass::Get_Embedded_Sound_Name(motion0);
543 if (sound_name) {
544 int bone_index = Get_Bone_Index(sound_name);
545 motion0->Set_Embedded_Sound_Bone_Index(bone_index);
546 }
547 }
548
549 if ( ModeInterp.Motion1 != NULL ) {
550 ModeInterp.Motion1->Add_Ref();
551 const char* sound_name = AnimatedSoundMgrClass::Get_Embedded_Sound_Name(motion1);
552 if (sound_name) {
553 int bone_index = Get_Bone_Index(sound_name);
554 motion1->Set_Embedded_Sound_Bone_Index(bone_index);
555 }
556 }
557}
558
559
560/***********************************************************************************************
561 * Animatable3DObjClass::Set_Animation -- Set animation state with an anim combo *
562 * *
563 * INPUT: *
564 * *
565 * OUTPUT: *
566 * *
567 * WARNINGS: *
568 * *
569 * HISTORY: *
570 * 12/8/98 GTH : Created. *
571 *=============================================================================================*/
573(
574 HAnimComboClass * anim_combo
575)
576{
577 Release();
578
580 ModeCombo.AnimCombo = anim_combo;
581 Set_Hierarchy_Valid(false);
582
583 if (anim_combo) {
584 int count = anim_combo->Get_Num_Anims();
585 for (int index = 0; index < count; index ++) {
586 HAnimClass *motion = anim_combo->Peek_Motion(index);
587
588 const char* sound_name = AnimatedSoundMgrClass::Get_Embedded_Sound_Name(motion);
589 if (sound_name) {
590 int bone_index = Get_Bone_Index(sound_name);
591 motion->Set_Embedded_Sound_Bone_Index(bone_index);
592 }
593 }
594 }
595}
596
597
598/***********************************************************************************************
599 * Animatable3DObjClass::Peek_Animation *
600 * *
601 * INPUT: *
602 * *
603 * OUTPUT: *
604 * *
605 * WARNINGS: *
606 * *
607 * HISTORY: *
608 * 12/8/98 GTH : Created. *
609 *=============================================================================================*/
611{
612 if ( CurMotionMode == SINGLE_ANIM ) {
613 return ModeAnim.Motion;
614 } else {
615 return NULL;
616 }
617}
618
619
620/***********************************************************************************************
621 * Animatable3DObjClass::Get_Bone_Transform -- return the transform for the given bone *
622 * *
623 * INPUT: *
624 * *
625 * OUTPUT: *
626 * *
627 * WARNINGS: *
628 * *
629 * HISTORY: *
630 * 12/8/98 GTH : Created. *
631 *=============================================================================================*/
633{
634 if (HTree) {
636 WWASSERT(bonename);
637
638 int idx = HTree->Get_Bone_Index(bonename);
639 return Get_Bone_Transform(idx);
640 } else {
641 return Get_Transform();
642 }
643}
644
645
646/***********************************************************************************************
647 * Animatable3DObjClass::Get_Bone_Transform -- return the transform for the given bone *
648 * *
649 * INPUT: *
650 * *
651 * OUTPUT: *
652 * *
653 * WARNINGS: *
654 * *
655 * HISTORY: *
656 * 12/8/98 GTH : Created. *
657 *=============================================================================================*/
659{
661
662 if (HTree) {
663 /*
664 ** If our hierarchy isn't valid, we just need to evaluate our animation
665 ** state.
666 */
667 if (!Is_Hierarchy_Valid()) {
669 }
670
671 return HTree->Get_Transform(boneindex);
672 } else {
673 return Transform;
674 }
675}
676
677
678/***********************************************************************************************
679 * Animatable3DObjClass::Capture_Bone -- capture the specified bone (override animation) *
680 * *
681 * INPUT: *
682 * *
683 * OUTPUT: *
684 * *
685 * WARNINGS: *
686 * *
687 * HISTORY: *
688 * 3/2/99 GTH : Created. *
689 *=============================================================================================*/
691{
692 if (HTree) {
693 HTree->Capture_Bone(boneindex);
694 }
695}
696
697
698/***********************************************************************************************
699 * Animatable3DObjClass::Release_Bone -- release the specified bone (allow animation) *
700 * *
701 * INPUT: *
702 * *
703 * OUTPUT: *
704 * *
705 * WARNINGS: *
706 * *
707 * HISTORY: *
708 * 3/2/99 GTH : Created. *
709 *=============================================================================================*/
711{
712 if (HTree) {
713 HTree->Release_Bone(boneindex);
714 }
715}
716
717
718/***********************************************************************************************
719 * Animatable3DObjClass::Is_Bone_Captured -- returns whether the specified bone is captured *
720 * *
721 * INPUT: *
722 * *
723 * OUTPUT: *
724 * *
725 * WARNINGS: *
726 * *
727 * HISTORY: *
728 * 3/2/99 GTH : Created. *
729 *=============================================================================================*/
731{
732 if (HTree) {
733 return HTree->Is_Bone_Captured(boneindex);
734 } else {
735 return false;
736 }
737}
738
739
740/***********************************************************************************************
741 * Animatable3DObjClass::Control_Bone -- sets the transform for the bone *
742 * *
743 * INPUT: *
744 * *
745 * OUTPUT: *
746 * *
747 * WARNINGS: *
748 * *
749 * HISTORY: *
750 * 3/2/99 GTH : Created. *
751 *=============================================================================================*/
752void Animatable3DObjClass::Control_Bone(int bindex,const Matrix3D & objtm,bool world_space_translation)
753{
754#ifdef WWDEBUG
755 for (int j=0; j<3; j++) {
756 for (int i=0; i<4; i++) {
757 WWASSERT(WWMath::Is_Valid_Float(objtm[j][i]));
758 }
759 }
760#endif
761
762 if (HTree) {
763 HTree->Control_Bone(bindex,objtm,world_space_translation);
764 Set_Hierarchy_Valid(false);
765 }
766}
767
768/***********************************************************************************************
769 * Animatable3DObjClass::Update_Sub_Object_Transforms -- recalculate the transforms for our su *
770 * *
771 * INPUT: *
772 * *
773 * OUTPUT: *
774 * *
775 * WARNINGS: *
776 * *
777 * HISTORY: *
778 * 12/8/98 GTH : Created. *
779 *=============================================================================================*/
781{
782 /*
783 ** The RenderObj impementation will cause our 'container'
784 ** to update if we are not valid yet
785 */
787
788 /*
789 ** Update the transforms
790 */
791 switch (CurMotionMode) {
792
793 case BASE_POSE:
795 break;
796
797 case SINGLE_ANIM:
798
799 if ( ModeAnim.AnimMode != ANIM_MODE_MANUAL ) {
801 }
803
804 /*
805 ** Play any sounds that are triggered by this frame of animation
806 */
807 if ( ModeAnim.Motion->Has_Embedded_Sounds() ) {
808 ModeAnim.PrevFrame = AnimatedSoundMgrClass::Trigger_Sound(ModeAnim.Motion, ModeAnim.PrevFrame, ModeAnim.Frame, HTree->Get_Transform(ModeAnim.Motion->Get_Embedded_Sound_Bone_Index()));
809 }
810 break;
811
812 case DOUBLE_ANIM:
814 ModeInterp.Motion1,ModeInterp.Frame1,ModeInterp.Percentage);
815
816 /*
817 ** Play any sounds that are triggered by this frame of animation
818 */
819 if ( ModeInterp.Motion0->Has_Embedded_Sounds() ) {
820 ModeInterp.PrevFrame0 = AnimatedSoundMgrClass::Trigger_Sound(ModeInterp.Motion0, ModeInterp.PrevFrame0, ModeInterp.Frame0, HTree->Get_Transform(ModeInterp.Motion0->Get_Embedded_Sound_Bone_Index()));
821 }
822
823 if ( ModeInterp.Motion1->Has_Embedded_Sounds() ) {
824 ModeInterp.PrevFrame1 = AnimatedSoundMgrClass::Trigger_Sound(ModeInterp.Motion1, ModeInterp.PrevFrame1, ModeInterp.Frame1, HTree->Get_Transform(ModeInterp.Motion1->Get_Embedded_Sound_Bone_Index()));
825 }
826
827 break;
828
829 case MULTIPLE_ANIM:
830 {
832
833 /*
834 ** Play any sounds that are triggered by this frame of animation
835 */
836 int count = ModeCombo.AnimCombo->Get_Num_Anims();
837 for (int index = 0; index < count; index ++) {
838 HAnimClass *motion = ModeCombo.AnimCombo->Peek_Motion(index);
839
840 if ( motion != NULL && motion->Has_Embedded_Sounds() ) {
841 float prev_frame = AnimatedSoundMgrClass::Trigger_Sound(motion, ModeCombo.AnimCombo->Get_Prev_Frame(index),
842 ModeCombo.AnimCombo->Get_Frame(index), HTree->Get_Transform(motion->Get_Embedded_Sound_Bone_Index()));
843 ModeCombo.AnimCombo->Set_Prev_Frame(index, prev_frame);
844 }
845
846 }
847 break;
848 }
849
850 default:
851 break;
852 }
854}
855
856
857/***********************************************************************************************
858 * Animatable3DObjClass::Simple_Evaluate_Bone -- If the animation is 'single', evaluate the *
859 * given pivot and return its transform. *
860 * *
861 * INPUT: *
862 * *
863 * OUTPUT: *
864 * *
865 * WARNINGS: *
866 * *
867 * HISTORY: *
868 * 04/13/2000 PDS : Created. *
869 *=============================================================================================*/
871{
872 bool retval = false;
873
874 //
875 // Only do this for simple animations
876 //
877 if ( CurMotionMode == NONE ||
880 {
881 //
882 // Determine which frame we should be on, then use this
883 // information to determine the bone's transform.
884 //
885 float curr_frame = Compute_Current_Frame ();
886 retval = Simple_Evaluate_Bone (boneindex, curr_frame, tm);
887
888 } else {
889
891 *tm = HTree->Get_Transform(boneindex);
892
893 }
894
895 return retval;
896}
897
898
899/***********************************************************************************************
900 * Animatable3DObjClass::Simple_Evaluate_Bone -- If the animation is 'single', evaluate the *
901 * given pivot and return its transform. *
902 * *
903 * INPUT: *
904 * *
905 * OUTPUT: *
906 * *
907 * WARNINGS: *
908 * *
909 * HISTORY: *
910 * 04/13/2000 PDS : Created. *
911 *=============================================================================================*/
912bool Animatable3DObjClass::Simple_Evaluate_Bone(int boneindex, float frame, Matrix3D *tm) const
913{
914 bool retval = false;
915
916 //
917 // Only do this for simple animations
918 //
919 if (HTree != NULL) {
920
921 if (CurMotionMode == SINGLE_ANIM) {
922 retval = HTree->Simple_Evaluate_Pivot (ModeAnim.Motion, boneindex, frame, Get_Transform (), tm);
923 } else if (CurMotionMode == NONE || CurMotionMode == BASE_POSE) {
924 retval = HTree->Simple_Evaluate_Pivot (boneindex, Get_Transform (), tm);
925 } else {
926 *tm = Transform;
927 }
928
929 } else {
930 *tm = Transform;
931 }
932
933 return retval;
934}
935
936
937/***********************************************************************************************
938 * Animatable3DObjClass::Compute_Current_Frame -- Returns the animation frame for the next rend*
939 * *
940 * INPUT: *
941 * *
942 * OUTPUT: *
943 * *
944 * WARNINGS: Only works for Single and CSingle! *
945 * *
946 * HISTORY: *
947 * 04/13/2000 PDS : Created. *
948 *=============================================================================================*/
949float Animatable3DObjClass::Compute_Current_Frame(float *newDirection) const
950{
951 float frame = 0;
952 float direction = ModeAnim.animDirection;
953
954 switch (CurMotionMode)
955 {
956 case SINGLE_ANIM:
957 {
958 frame = ModeAnim.Frame;
959
960 //
961 // Compute the current frame based on elapsed time.
962 //
963 if (ModeAnim.AnimMode != ANIM_MODE_MANUAL) {
964 float sync_time_diff = WW3D::Get_Sync_Time() - ModeAnim.LastSyncTime;
965 float delta = ModeAnim.Motion->Get_Frame_Rate() * ModeAnim.frameRateMultiplier * ModeAnim.animDirection * sync_time_diff * 0.001f;
966 frame += delta;
967
968 //
969 // Wrap the frame
970 //
971 switch (ModeAnim.AnimMode)
972 {
973 case ANIM_MODE_ONCE:
974 if (frame >= ModeAnim.Motion->Get_Num_Frames() - 1) {
975 frame = ModeAnim.Motion->Get_Num_Frames() - 1;
976 }
977 break;
978 case ANIM_MODE_LOOP:
979 if ( frame >= ModeAnim.Motion->Get_Num_Frames() - 1 ) {
980 frame -= ModeAnim.Motion->Get_Num_Frames() - 1;
981 }
982 // If it is still too far out, reset
983 if ( frame >= ModeAnim.Motion->Get_Num_Frames() - 1 ) {
984 frame = 0;
985 }
986 break;
987 case ANIM_MODE_ONCE_BACKWARDS: //play animation one time but backwards
988 if (frame < 0) {
989 frame = 0;
990 }
991 break;
992 case ANIM_MODE_LOOP_BACKWARDS: //play animation backwards in a loop
993 if ( frame < 0 ) {
994 frame += ModeAnim.Motion->Get_Num_Frames() - 1;
995 }
996 // If it is still too far out, reset
997 if ( frame < 0 ) {
998 frame = ModeAnim.Motion->Get_Num_Frames() - 1;
999 }
1000 break;
1002 if (ModeAnim.animDirection >= 1.0f)
1003 { //playing forwards, reverse direction
1004 if (frame >= (ModeAnim.Motion->Get_Num_Frames() - 1))
1005 { //step backwards in animation by excess time
1006 frame = (ModeAnim.Motion->Get_Num_Frames() - 1)*2 - frame;
1007 // If it is still too far out, reset
1008 if ( frame >= ModeAnim.Motion->Get_Num_Frames() - 1 )
1009 frame = (ModeAnim.Motion->Get_Num_Frames() - 1);
1010 direction = ModeAnim.animDirection * -1.0f;
1011 }
1012 }
1013 else
1014 { //playing backwards, reverse direction
1015 if (frame < 0)
1016 { //step forwards in animation by excess time
1017 frame = -frame;
1018 // If it is still too far out, reset
1019 if ( frame >= ModeAnim.Motion->Get_Num_Frames() - 1 )
1020 frame = 0;
1021 direction = ModeAnim.animDirection * -1.0f;
1022 }
1023 }
1024 break;
1025 }
1026 }
1027 }
1028 break;
1029 }
1030
1031 if (newDirection)
1032 *newDirection = direction;
1033 return frame;
1034}
1035
1036/***********************************************************************************************
1037 * Animatable3DObjClass::Single_Anim_Progress -- progess anims for loop and once *
1038 * *
1039 * INPUT: *
1040 * *
1041 * OUTPUT: *
1042 * *
1043 * WARNINGS: Only works for Single and CSingle *
1044 * *
1045 * HISTORY: *
1046 * 10/26/99 BMG : Created. *
1047 *=============================================================================================*/
1049{
1050 //
1051 // Update the current frame (only works in "SINGLE_ANIM" mode!)
1052 //
1053 if (CurMotionMode == SINGLE_ANIM) {
1054
1055 //
1056 // Update the frame number and sync time
1057 //
1058 float oldprev = ModeAnim.PrevFrame;
1059 ModeAnim.PrevFrame = ModeAnim.Frame;
1060 ModeAnim.Frame = Compute_Current_Frame(&ModeAnim.animDirection);
1061 ModeAnim.LastSyncTime = WW3D::Get_Sync_Time();
1062
1063 if (ModeAnim.Frame == ModeAnim.PrevFrame) {
1064 // This function was somehow called twice per frame.
1065 // Since ModeAnim.Frame hasn't changed, reset the ModeAnim.PrevFrame.
1066 // If you don't do this sounds won't be triggered properly because Frame and PrevFrame will be the same.
1067 ModeAnim.PrevFrame = oldprev;
1068 }
1069 //
1070 // Force the heirarchy to be recalculated
1071 //
1072 Set_Hierarchy_Valid (false);
1073 }
1074}
1075
1076
1077/***********************************************************************************************
1078 * Animatable3DObjClass::Is_Animation_Complete -- is the current animation on the last frame? *
1079 * *
1080 * INPUT: *
1081 * *
1082 * OUTPUT: *
1083 * *
1084 * WARNINGS: Only works for Single, ONCE anims *
1085 * *
1086 * HISTORY: *
1087 * 4/13/99 BMG : Created. *
1088 *=============================================================================================*/
1090{
1091 if (CurMotionMode == SINGLE_ANIM) {
1092
1093 if ( ModeAnim.AnimMode == ANIM_MODE_ONCE ) {
1094 return ( ModeAnim.Frame == ModeAnim.Motion->Get_Num_Frames() - 1 );
1095 }
1096 else
1097 if ( ModeAnim.AnimMode == ANIM_MODE_ONCE_BACKWARDS)
1098 { return ( ModeAnim.Frame == 0);
1099 }
1100 }
1101 return false;
1102}
1103
1104/***********************************************************************************************
1105 * Animatable3DObjClass::Peek_Animation_And_Info *
1106 *=============================================================================================*/
1107HAnimClass * Animatable3DObjClass::Peek_Animation_And_Info(float& frame, int& numFrames, int& mode, float& mult)
1108{
1109 if ( CurMotionMode == SINGLE_ANIM ) {
1110 frame = ModeAnim.Frame;
1111 numFrames = ModeAnim.Motion ? ModeAnim.Motion->Get_Num_Frames() : 0;
1112 mode = ModeAnim.AnimMode;
1113 mult = ModeAnim.frameRateMultiplier;
1114 return ModeAnim.Motion;
1115 } else {
1116 return NULL;
1117 }
1118}
1119
1120/***********************************************************************************************
1121 * Animatable3DObjClass::Set_Animation_Frame_Rate_Multiplier *
1122 *=============================================================================================*/
1124{
1125 // 020607 srj -- added
1126 ModeAnim.frameRateMultiplier = multiplier;
1127}
1128
1129// (gth) TESTING DYNAMICALLY SWAPPING SKELETONS!
1130
1132{
1134 // try to ensure that the htree we're using has the same structure...
1135 WWASSERT(new_htree->Num_Pivots() == HTree->Num_Pivots());
1136
1137 // just assign it...
1138 if (HTree != NULL) {
1139 delete HTree;
1140 }
1141 HTree = W3DNEW HTreeClass(*new_htree);
1142}
1143
1144
1145// EOF - animobj.cpp
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define W3DNEW
Definition always.h:109
virtual const Matrix3D & Get_Bone_Transform(const char *bonename)
Definition animobj.cpp:632
virtual bool Simple_Evaluate_Bone(int boneindex, Matrix3D *tm) const
Definition animobj.cpp:870
void Set_Hierarchy_Valid(bool onoff) const
Definition animobj.h:158
virtual HAnimClass * Peek_Animation_And_Info(float &frame, int &numFrames, int &mode, float &mult)
Definition animobj.cpp:1107
Animatable3DObjClass(const char *htree_name)
Definition animobj.cpp:84
virtual void Render(RenderInfoClass &rinfo)
Definition animobj.cpp:288
virtual void Update_Sub_Object_Transforms(void)
Definition animobj.cpp:780
virtual bool Is_Bone_Captured(int boneindex) const
Definition animobj.cpp:730
float Compute_Current_Frame(float *newDirection=NULL) const
Definition animobj.cpp:949
struct Animatable3DObjClass::@274255212152070234202005354334045134277330066032::@107271141224054257360210075076210275034114224025 ModeInterp
virtual void Control_Bone(int bindex, const Matrix3D &objtm, bool world_space_translation=false)
Definition animobj.cpp:752
Animatable3DObjClass & operator=(const Animatable3DObjClass &)
Definition animobj.cpp:198
virtual int Get_Bone_Index(const char *bonename)
Definition animobj.cpp:429
bool Is_Hierarchy_Valid(void) const
Definition animobj.h:157
virtual void Special_Render(SpecialRenderInfoClass &rinfo)
Definition animobj.cpp:319
virtual void Set_HTree(HTreeClass *htree)
Definition animobj.cpp:1131
struct Animatable3DObjClass::@274255212152070234202005354334045134277330066032::@265165303263313322022336070002244172025153143316 ModeCombo
virtual HAnimClass * Peek_Animation(void)
Definition animobj.cpp:610
struct Animatable3DObjClass::@274255212152070234202005354334045134277330066032::@111374312050245341017050215151003212205312230222 ModeAnim
virtual void Release_Bone(int boneindex)
Definition animobj.cpp:710
void Base_Update(const Matrix3D &root)
Definition animobj.h:235
virtual void Set_Animation_Frame_Rate_Multiplier(float multiplier)
Definition animobj.cpp:1123
virtual void Set_Animation(void)
Definition animobj.cpp:452
virtual bool Is_Animation_Complete(void) const
Definition animobj.cpp:1089
void Blend_Update(const Matrix3D &root, HAnimClass *motion0, float frame0, HAnimClass *motion1, float frame1, float percentage)
Definition animobj.h:287
virtual int Get_Num_Bones(void)
Definition animobj.cpp:385
virtual const char * Get_Bone_Name(int bone_index)
Definition animobj.cpp:407
void Single_Anim_Progress(void)
Definition animobj.cpp:1048
void Combo_Update(const Matrix3D &root, HAnimComboClass *anim)
Definition animobj.h:318
void Anim_Update(const Matrix3D &root, HAnimClass *motion, float frame)
Definition animobj.h:259
virtual void Set_Position(const Vector3 &v)
Definition animobj.cpp:366
virtual void Capture_Bone(int boneindex)
Definition animobj.cpp:690
virtual void Set_Transform(const Matrix3D &m)
Definition animobj.cpp:347
HTreeClass * HTree
Definition animobj.h:172
virtual ~Animatable3DObjClass(void)
Definition animobj.cpp:176
static const char * Get_Embedded_Sound_Name(HAnimClass *anim)
static float Trigger_Sound(HAnimClass *anim, float old_frame, float new_frame, const Matrix3D &tm)
CompositeRenderObjClass & operator=(const CompositeRenderObjClass &that)
virtual bool Has_Embedded_Sounds(void) const
Definition hanim.h:120
virtual int Get_Embedded_Sound_Bone_Index()
Definition hanim.h:122
virtual void Set_Embedded_Sound_Bone_Index(int bone)
Definition hanim.h:121
HAnimClass * Peek_Motion(int indx)
Definition hanim.cpp:377
int Get_Num_Anims(void)
Definition hanim.h:239
WWINLINE int Num_Pivots(void) const
Definition htree.h:93
void Add_Ref(void) const
Definition refcount.cpp:171
virtual void Set_Transform(const Matrix3D &m)
Definition rendobj.cpp:423
virtual int Is_Not_Hidden_At_All(void)
Definition rendobj.h:463
@ ANIM_MODE_LOOP_PINGPONG
Definition rendobj.h:336
@ ANIM_MODE_LOOP_BACKWARDS
Definition rendobj.h:337
@ ANIM_MODE_ONCE_BACKWARDS
Definition rendobj.h:338
virtual void Set_Position(const Vector3 &v)
Definition rendobj.cpp:444
virtual void Update_Sub_Object_Transforms(void)
Definition rendobj.cpp:777
bool Are_Sub_Object_Transforms_Dirty(void)
Definition rendobj.h:495
const Matrix3D & Get_Transform(void) const
Definition rendobj.h:617
virtual void Validate_Transform(void) const
Definition rendobj.cpp:464
Matrix3D Transform
Definition rendobj.h:549
static WW3DAssetManager * Get_Instance(void)
Definition assetmgr.h:205
virtual HTreeClass * Get_HTree(const char *name)
static unsigned int Get_Sync_Time(void)
Definition ww3d.h:172
static bool Is_Valid_Float(float x)
Definition wwmath.h:281
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114
@ MEM_ANIMATION
Definition wwmemlog.h:60
#define WWMEMLOG(category)
Definition wwmemlog.h:183