Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
hanim.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/* $Header: /Commando/Code/ww3d2/hanim.cpp 3 12/13/01 7:01p Patrick $ */
20/***********************************************************************************************
21 *** Confidential - Westwood Studios ***
22 ***********************************************************************************************
23 * *
24 * Project Name : Commando / G 3D Library *
25 * *
26 * $Archive:: /Commando/Code/ww3d2/hanim.cpp $*
27 * *
28 * Author:: Greg_h *
29 * *
30 * $Modtime:: 12/13/01 6:54p $*
31 * *
32 * $Revision:: 3 $*
33 * *
34 *---------------------------------------------------------------------------------------------*
35 * Functions: *
36 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
37
38
39#include "hanim.h"
40#include "assetmgr.h"
41#include "htree.h"
42#include "motchan.h"
43#include "chunkio.h"
44#include "w3d_file.h"
45#include "wwdebug.h"
46#include <string.h>
47#include <nstrdup.h>
48
49
50
51/*
52**
53** HAnimComboClass
54**
55**
56*/
57
58
62
63NamedPivotMapClass::WeightInfoStruct & NamedPivotMapClass::WeightInfoStruct::operator = (WeightInfoStruct const &that)
64{
65 if(Name) delete [] Name;
66 assert(that.Name != 0);
67 Name = nstrdup(that.Name);
68 Weight = that.Weight;
69 return *this;
70}
71
72// add a name & weight to the arrays
73void NamedPivotMapClass::Add(const char *Name, float Weight)
74{
75 WeightInfoStruct info;
76 info.Name = (char *) Name;
77 info.Weight = Weight;
78 WeightInfo.Add(info);
79 info.Name = 0;
80}
81
82// configure the base pivot map using the specified tree
84{
85 // first, resize the base pivot map to fit the tree
86 int numPivots = Tree->Num_Pivots();
87
88 Resize(numPivots);
89 ActiveCount = numPivots;
90
91 // first, reset all weights to 1 (the default)
92 while(numPivots--) {
93 (*this)[numPivots] = 1.0f;
94 }
95
96 // for each named pivot, find the correct index and set the weight if the indicated bone is present
97 // note: there is no check for redundant names
98 int count = WeightInfo.Count();
99 while(count--) {
100 int actualPivot = Tree->Get_Bone_Index(WeightInfo[count].Name);
101 if(actualPivot != -1) {
102 (*this)[actualPivot] = WeightInfo[count].Weight;
103 }
104 }
105}
106
107/*
108**
109*/
111
113: Shared(shared), HAnim(0), PivotMap(0), Frame(0), PrevFrame(0), Weight(1)
114{}
115
116
118: PivotMap(src.Get_Pivot_Map()),
119 HAnim(src.Get_HAnim())
120{
121 Shared = src.Is_Shared();
122 Frame = src.Get_Frame();
123 PrevFrame = src.Get_Prev_Frame();
124 Weight = src.Get_Weight();
125}
126
128{
129 if(src) {
130 HAnim = src->Get_HAnim();
131 PivotMap = src->Get_Pivot_Map();
132 Frame = src->Get_Frame();
133 PrevFrame = src->Get_Prev_Frame();
134 Weight = src->Get_Weight();
135 } else {
136 HAnim = 0;
137 PivotMap = 0;
138 Frame = 0;
139 PrevFrame = 0;
140 Weight = 1;
141 }
142}
143
145{
146 if(HAnim)
147 HAnim->Release_Ref();
148 if(PivotMap)
149 PivotMap->Release_Ref();
150}
151
153{
154 if ( HAnim != NULL ) {
155 HAnim->Release_Ref();
156 HAnim = NULL;
157 }
158
159 // not sure if the pivot map should be deleted or just have everything set to one.
160 // removing it effectively sets it to one, so that's what I'm doing for now.
161 if(PivotMap) {
162 PivotMap->Release_Ref();
163 PivotMap = NULL;
164 }
165
166 Frame = 0.0f;
167 PrevFrame = 0.0f;
168 Weight = 1.0;
169 PivotMap = NULL;
170}
171
173{
174 if ( motion != NULL ) {
175 motion->Add_Ref();
176 }
177 if ( HAnim != NULL ) {
178 HAnim->Release_Ref();
179 }
180 HAnim = motion;
181}
182
183
185{
186 if ( map != NULL ) {
187 map->Add_Ref();
188 }
189 if ( PivotMap != NULL ) {
190 PivotMap->Release_Ref();
191 }
192 PivotMap = map;
193}
194
195/*
196** This function will replace the current pivot map (if any) with another pivot map that is
197** set to 1 for only those pivot indices that actually have data.
198*/
200{
201 if ( PivotMap != NULL ) {
202 PivotMap->Release_Ref();
203 }
204 if(HAnim == NULL) {
205 PivotMap = 0;
206 return;
207 }
208
209 int numpivots = HAnim->Get_Num_Pivots();
210 PivotMap = NEW_REF( PivotMapClass, ());
211 PivotMap->Resize(numpivots);
212
213 int count = 0;
214 while(count < numpivots) {
215 if(HAnim->Is_Node_Motion_Present(count)) {
216 PivotMap->Add(1);
217
218 } else {
219 PivotMap->Add(0);
220 }
221 count++;
222 }
223}
224
225/*
226** HAnimComboClass
227**
228**
229*/
230
233
235{
236 HAnimComboData.Resize(num_animations);
237
238 while(num_animations--) {
240 }
241}
242
243
248
249
251{
252 int numAnimations = HAnimComboData.Count();
253 while ( numAnimations-- ) {
254 HAnimComboDataClass *data = HAnimComboData[numAnimations];
255 if(data && (! data->Is_Shared()))
256 data->Clear();
257 }
258}
259
261{
262 int numAnimations = HAnimComboData.Count();
263 while ( numAnimations-- ) {
264 HAnimComboDataClass *data = HAnimComboData[numAnimations];
265 if(data && (! data->Is_Shared())) {
266 delete data;
267 }
268 }
269 HAnimComboData.Reset_Active();
270}
271
273{
274 // NOTE: This can only work if either no anims have pivot weight maps (in which case we will
275 // adjust the anim weights to ensure normalization), or else if all do (in which case we will
276 // adjust the pivot maps). Otherwise we do nothing and return false.
277 int anim_count = Get_Num_Anims();
278 if (!anim_count) return true; // Trivially succeeded
279
280 // Loop over all anims. Check if all or none have pivot maps, and also calculate the minimum
281 // number of pivots.
282 int anim_idx = 0;
283 bool all_pivot_maps = true;
284 bool none_pivot_maps = true;
285 int num_anim_pivots = 100000;
286 for (anim_idx = 0; anim_idx < anim_count; anim_idx++ ) {
287 num_anim_pivots = MIN(num_anim_pivots, Peek_Motion(anim_idx)->Get_Num_Pivots());
288 bool has_pivot_map = Peek_Pivot_Weight_Map(anim_idx) != NULL;
289 all_pivot_maps &= has_pivot_map;
290 none_pivot_maps &= !has_pivot_map;
291 }
292 if ( num_anim_pivots == 100000 ) {
293 num_anim_pivots = 0;
294 }
295
296 if (none_pivot_maps) {
297
298 // Calculate total weight of all active anims, ensure it is very close to 1.
299 float weight_total = 0.0f;
300 for (anim_idx = 0; anim_idx < anim_count; anim_idx++ ) {
301 if (Peek_Motion(anim_idx) != NULL ) {
302 float weight = Get_Weight(anim_idx);
303 weight_total += weight;
304 }
305 }
306
307 // weight_total should be very close to 1. If not, normalize this pivot's weights
308 if (weight_total != 0.0 && WWMath::Fabs( weight_total - 1.0 ) > WWMATH_EPSILON) {
309 float oo_total = 1.0f / weight_total;
310 for (anim_idx = 0; anim_idx < anim_count; anim_idx++ ) {
311 if (Peek_Motion(anim_idx) != NULL ) {
312 Set_Weight(anim_idx, Get_Weight(anim_idx) * oo_total);
313 }
314 }
315 }
316
317 } else {
318
319 if (all_pivot_maps) {
320
321 // For each pivot, calculate total weight of all active anims, ensure close to 1.
322 for (int piv_idx = 1; piv_idx < num_anim_pivots; piv_idx++) {
323
324 float weight_total = 0.0f;
325 for (anim_idx = 0; anim_idx < anim_count; anim_idx++ ) {
326 if (Peek_Motion(anim_idx) != NULL ) {
327 float weight = Get_Weight(anim_idx) * (*Peek_Pivot_Weight_Map(anim_idx))[piv_idx];
328 weight_total += weight;
329 }
330 }
331
332 // weight_total should be very close to 1. If not, normalize this pivot's weights
333 if (weight_total != 0.0 && WWMath::Fabs( weight_total - 1.0 ) > WWMATH_EPSILON) {
334 float oo_total = 1.0f / weight_total;
335 for (anim_idx = 0; anim_idx < anim_count; anim_idx++ ) {
336 if (Peek_Motion(anim_idx) != NULL ) {
337 PivotMapClass *pivot_map = Get_Pivot_Weight_Map(anim_idx);
338 float new_weight = (*pivot_map)[piv_idx] * oo_total;
339 (*pivot_map)[piv_idx] = new_weight;
340 pivot_map->Release_Ref();
341 }
342 }
343 }
344
345 }
346
347 } else {
348 return false;
349 }
350 }
351
352 return true;
353
354}
355
356void HAnimComboClass::Set_Motion( int index, HAnimClass *motion )
357{
358 HAnimComboDataClass *data = HAnimComboData[index];
359 WWASSERT(data);
360
361 data->Set_HAnim(motion);
362}
363
365{
366 HAnimComboDataClass *data = HAnimComboData[index];
367 WWASSERT(data);
368
369 HAnimClass *anim = data->Peek_HAnim();
370
371 if ( anim != NULL ) {
372 anim->Add_Ref();
373 }
374 return anim;
375}
376
378{
379 HAnimComboDataClass *data = HAnimComboData[index];
380 WWASSERT(data);
381
382 HAnimClass *anim = data->Peek_HAnim();
383 return anim;
384}
385
386void HAnimComboClass::Set_Frame( int index, float frame )
387{
388 HAnimComboDataClass *data = HAnimComboData[index];
389 WWASSERT(data);
390
391 data->Set_Frame(frame);
392}
393
395{
396 HAnimComboDataClass *data = HAnimComboData[index];
397 WWASSERT(data);
398
399 return data->Get_Frame();
400}
401
402void HAnimComboClass::Set_Prev_Frame( int index, float frame )
403{
404 HAnimComboDataClass *data = HAnimComboData[index];
405 WWASSERT(data);
406
407 data->Set_Prev_Frame(frame);
408}
409
411{
412 HAnimComboDataClass *data = HAnimComboData[index];
413 WWASSERT(data);
414
415 return data->Get_Prev_Frame();
416}
417
418void HAnimComboClass::Set_Weight( int index, float weight )
419{
420 HAnimComboDataClass *data = HAnimComboData[index];
421 WWASSERT(data);
422
423 data->Set_Weight(weight);
424}
425
427{
428 HAnimComboDataClass *data = HAnimComboData[index];
429 WWASSERT(data);
430
431 return data->Get_Weight();
432}
433
435{
436 HAnimComboDataClass *data = HAnimComboData[index];
437 WWASSERT(data);
438
439 data->Set_Pivot_Map(map);
440}
441
443{
444 HAnimComboDataClass *data = HAnimComboData[index];
445 WWASSERT(data);
446
447 return data->Get_Pivot_Map();
448}
449
451{
452 HAnimComboDataClass *data = HAnimComboData[index];
453 WWASSERT(data);
454
455 return data->Peek_Pivot_Map();
456}
457
462
467
468
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define MIN(a, b)
Definition always.h:189
#define WWMATH_EPSILON
Definition wwmath.h:54
virtual bool Resize(int newsize, float const *array=0)
Definition Vector.H:615
void Append_Anim_Combo_Data(HAnimComboDataClass *AnimComboData)
Definition hanim.cpp:458
DynamicVectorClass< HAnimComboDataClass * > HAnimComboData
Definition hanim.h:269
float Get_Prev_Frame(int indx)
Definition hanim.cpp:410
float Get_Frame(int indx)
Definition hanim.cpp:394
void Set_Weight(int indx, float weight)
Definition hanim.cpp:418
float Get_Weight(int indx)
Definition hanim.cpp:426
void Set_Pivot_Weight_Map(int indx, PivotMapClass *map)
Definition hanim.cpp:434
HAnimClass * Get_Motion(int indx)
Definition hanim.cpp:364
HAnimClass * Peek_Motion(int indx)
Definition hanim.cpp:377
void Remove_Anim_Combo_Data(HAnimComboDataClass *AnimComboData)
Definition hanim.cpp:463
PivotMapClass * Peek_Pivot_Weight_Map(int indx)
Definition hanim.cpp:450
void Set_Frame(int indx, float frame)
Definition hanim.cpp:386
HAnimComboClass(void)
Definition hanim.cpp:231
void Set_Prev_Frame(int indx, float frame)
Definition hanim.cpp:402
PivotMapClass * Get_Pivot_Weight_Map(int indx)
Definition hanim.cpp:442
void Reset(void)
Definition hanim.cpp:260
void Clear(void)
Definition hanim.cpp:250
bool Normalize_Weights(void)
Definition hanim.cpp:272
void Set_Motion(int indx, HAnimClass *motion)
Definition hanim.cpp:356
int Get_Num_Anims(void)
Definition hanim.h:239
~HAnimComboClass(void)
Definition hanim.cpp:244
float Get_Prev_Frame(void) const
Definition hanim.h:205
void Set_Weight(float weight)
Definition hanim.h:198
void Copy(const HAnimComboDataClass *)
Definition hanim.cpp:127
void Set_Frame(float frame)
Definition hanim.h:196
PivotMapClass * Peek_Pivot_Map(void) const
Definition hanim.h:207
HAnimClass * Peek_HAnim(void) const
Definition hanim.h:202
~HAnimComboDataClass(void)
Definition hanim.cpp:144
void Set_HAnim(HAnimClass *motion)
Definition hanim.cpp:172
void Build_Active_Pivot_Map(void)
Definition hanim.cpp:199
HAnimClass * Get_HAnim(void) const
Definition hanim.h:203
void Clear(void)
Definition hanim.cpp:152
PivotMapClass * Get_Pivot_Map(void) const
Definition hanim.h:208
bool Is_Shared(void) const
Definition hanim.h:209
void Set_Pivot_Map(PivotMapClass *map)
Definition hanim.cpp:184
void Set_Prev_Frame(float frame)
Definition hanim.h:197
float Get_Frame(void) const
Definition hanim.h:204
HAnimComboDataClass(bool shared=false)
Definition hanim.cpp:112
float Get_Weight(void) const
Definition hanim.h:206
WWINLINE int Num_Pivots(void) const
Definition htree.h:93
int Get_Bone_Index(const char *name) const
Definition htree.cpp:922
void Add(const char *Name, float Weight)
Definition hanim.cpp:73
void Update_Pivot_Map(const HTreeClass *Tree)
Definition hanim.cpp:83
~NamedPivotMapClass(void)
Definition hanim.cpp:59
WWINLINE void Release_Ref(void) const
Definition refcount.h:146
void Add_Ref(void) const
Definition refcount.cpp:171
static WWINLINE float Fabs(float val)
Definition wwmath.h:113
#define DEFINE_AUTO_POOL(T, BLOCKSIZE)
Definition mempool.h:160
char * nstrdup(const char *str)
Definition nstrdup.cpp:56
#define NEW_REF(C, P)
Definition refcount.h:62