Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
curve.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 : WWMath *
24 * *
25 * $Archive:: /VSS_Sync/wwmath/curve.cpp $*
26 * *
27 * Original Author:: Greg Hjelstrom *
28 * *
29 * $Author:: Vss_sync $*
30 * *
31 * $Modtime:: 6/13/01 2:18p $*
32 * *
33 * $Revision:: 9 $*
34 * *
35 *---------------------------------------------------------------------------------------------*
36 * Functions: *
37 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
38
39
40#include "curve.h"
41#include "wwdebug.h"
42#include "persistfactory.h"
43#include "wwmathids.h"
44#include "wwhack.h"
45
46/*
47** Force-Link this module because the linker can't detect that we actually need it...
48*/
50
51/*
52** Persist factories and chunk-id's used to save and load.
53*/
56
57enum
58{
59 // ID's used by Curve3D
62
65
66 // ID's used by LinearCurve3D
68
69 // ID's used by Curve1D
72
75
76 // ID's used by LinearCurve1D
78
79};
80
81
82/***********************************************************************************************
83**
84** Curve3DCLass Implementation
85**
86***********************************************************************************************/
91
93{
94 *this = that;
95}
96
100
102{
103 IsLooping = that.IsLooping;
104 Keys = that.Keys;
105 return *this;
106}
107
109{
110 return IsLooping;
111}
112
114{
115 IsLooping = onoff;
116}
117
119{
120 if (Keys.Count() > 0) {
121 return Keys[0].Time;
122 } else {
123 return 0.0f;
124 }
125}
126
128{
129 if (Keys.Count() > 0) {
130 return Keys[Keys.Count() - 1].Time;
131 } else {
132 return 0.0f;
133 }
134}
135
137{
138 return Keys.Count();
139}
140
141void Curve3DClass::Get_Key(int i,Vector3 * set_point,float * set_t)
142{
143 assert(i >= 0);
144 assert(i < Keys.Count());
145 if (set_point != NULL) {
146 *set_point = Keys[i].Point;
147 }
148 if (set_t != NULL) {
149 *set_t = Keys[i].Time;
150 }
151}
152
153void Curve3DClass::Set_Key(int i,const Vector3 & point)
154{
155 assert(i >= 0);
156 assert(i < Keys.Count());
157 Keys[i].Point = point;
158}
159
160
161int Curve3DClass::Add_Key(const Vector3 & point,float t)
162{
163 int idx = 0;
164 while (idx < Keys.Count() && Keys[idx].Time < t) {
165 idx++;
166 }
167
168 KeyClass newkey;
169 newkey.Point = point;
170 newkey.Time = t;
171
172 Keys.Insert(idx,newkey);
173 return idx;
174}
175
177{
178 assert(i >= 0);
179 assert(i < Keys.Count());
180 Keys.Delete(i);
181}
182
184{
185 Keys.Clear();
186}
187
188void Curve3DClass::Find_Interval(float time,int * i0,int * i1,float * t)
189{
190 WWASSERT(time >= Keys[0].Time);
191 WWASSERT(time <= Keys[Keys.Count()-1].Time);
192
193 int i=0;
194 while (time > Keys[i+1].Time) {
195 i++;
196 }
197 *i0 = i;
198 *i1 = i+1;
199 *t = (time - Keys[i].Time) / (Keys[i+1].Time - Keys[i].Time);
200}
201
203{
204 int keycount = Keys.Count();
208 csave.End_Chunk();
209
210 // Saving the keys, Note that if the format of a key changes we'll
211 // need a new chunk. (I didn't wrap each variable in its own chunk)
213 for (int i=0; i<keycount; i++) {
214 csave.Write(&(Keys[i].Point),sizeof(Keys[i].Point));
215 csave.Write(&(Keys[i].Time),sizeof(Keys[i].Time));
216 }
217 csave.End_Chunk();
218 return true;
219}
220
222{
223 int i;
224 int keycount = 0;
225 KeyClass newkey;
226
227 // reset the curve
228 Keys.Delete_All();
229
230 // read in the chunks
231 while (cload.Open_Chunk()) {
232
233 switch(cload.Cur_Chunk_ID())
234 {
236
237 while (cload.Open_Micro_Chunk()) {
238 switch(cload.Cur_Micro_Chunk_ID()) {
241 }
242 cload.Close_Micro_Chunk();
243 }
244 break;
245
247 for (i=0; i<keycount; i++) {
248 cload.Read(&(newkey.Point),sizeof(newkey.Point));
249 cload.Read(&(newkey.Time),sizeof(newkey.Time));
250 Keys.Add(newkey);
251 }
252 break;
253
254 default:
255 WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",__FILE__,__LINE__));
256 break;
257 }
258 cload.Close_Chunk();
259 }
260
261 return true;
262}
263
264
265
266/***********************************************************************************************
267**
268** LinearCurve3DClass Implementation
269** Linear curve, linearly interpolates the keys
270**
271***********************************************************************************************/
272void LinearCurve3DClass::Evaluate(float time,Vector3 * set_val)
273{
274 if (time < Keys[0].Time) {
275 *set_val = Keys[0].Point;
276 return;
277 }
278
279 if (time >= Keys[Keys.Count() - 1].Time) {
280 *set_val = Keys[Keys.Count() - 1].Point;
281 return;
282 }
283
284 int i0,i1;
285 float t;
286 Find_Interval(time,&i0,&i1,&t);
287
288 *set_val = Keys[i0].Point + t * (Keys[i1].Point - Keys[i0].Point);
289}
290
295
297{
299 Curve3DClass::Save(csave);
300 csave.End_Chunk();
301 return true;
302}
303
305{
306 while (cload.Open_Chunk()) {
307
308 switch(cload.Cur_Chunk_ID())
309 {
311 Curve3DClass::Load(cload);
312 break;
313
314 default:
315 WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",__FILE__,__LINE__));
316 break;
317 }
318 cload.Close_Chunk();
319 }
320
321 return true;
322}
323
324
325/***********************************************************************************************
326**
327** Curve1DClass
328**
329***********************************************************************************************/
334
336{
337 *this = that;
338}
339
343
345{
346 IsLooping = that.IsLooping;
347 Keys = that.Keys;
348 return *this;
349}
350
352{
353 return IsLooping;
354}
355
357{
358 IsLooping = onoff;
359}
360
362{
363 if (Keys.Count() > 0) {
364 return Keys[0].Time;
365 } else {
366 return 0.0f;
367 }
368}
369
371{
372 if (Keys.Count() > 0) {
373 return Keys[Keys.Count() - 1].Time;
374 } else {
375 return 0.0f;
376 }
377}
378
380{
381 return Keys.Count();
382}
383
384void Curve1DClass::Get_Key(int i,float * set_point,float * set_t,unsigned int * extra)
385{
386 assert(i >= 0);
387 assert(i < Keys.Count());
388 if (set_point != NULL) {
389 *set_point = Keys[i].Point;
390 }
391 if (set_t != NULL) {
392 *set_t = Keys[i].Time;
393 }
394 if (extra != NULL) {
395 *extra = Keys[i].Extra;
396 }
397}
398
399void Curve1DClass::Set_Key(int i,float point,unsigned int extra)
400{
401 assert(i >= 0);
402 assert(i < Keys.Count());
403 Keys[i].Point = point;
404 Keys[i].Extra = extra;
405}
406
407
408int Curve1DClass::Add_Key(float point,float t,unsigned int extra)
409{
410 int idx = 0;
411 while (idx < Keys.Count() && Keys[idx].Time < t) {
412 idx++;
413 }
414
415 KeyClass newkey;
416 newkey.Point = point;
417 newkey.Time = t;
418 newkey.Extra = extra;
419
420 Keys.Insert(idx,newkey);
421 return idx;
422}
423
425{
426 assert(i >= 0);
427 assert(i < Keys.Count());
428 Keys.Delete(i);
429}
430
432{
433 Keys.Clear();
434}
435
436void Curve1DClass::Find_Interval(float time,int * i0,int * i1,float * t)
437{
438 if (IsLooping) {
439 if (time < Keys[0].Time) {
440 *i0 = Keys.Count() - 1;
441 *i1 = 0;
442 float interval = 1.0f - Keys[*i0].Time + Keys[*i1].Time;
443 *t = (1.0f - Keys[*i0].Time + time) / interval;
444 return;
445 }
446 else if (time > Keys[Keys.Count() - 1].Time) {
447 *i0 = Keys.Count() - 1;
448 *i1 = 0;
449 float interval = 1.0f - Keys[*i0].Time + Keys[*i1].Time;
450 *t = (time - Keys[*i0].Time) / interval;
451 return;
452 }
453 }
454 else {
455 WWASSERT(time >= Keys[0].Time);
456 WWASSERT(time <= Keys[Keys.Count()-1].Time);
457 }
458
459 int i=0;
460 while (time > Keys[i+1].Time) {
461 i++;
462 }
463 *i0 = i;
464 *i1 = i+1;
465 *t = (time - Keys[i].Time) / (Keys[i+1].Time - Keys[i].Time);
466}
467
469{
470 int keycount = Keys.Count();
474 csave.End_Chunk();
475
476 // Saving the keys, Note that if the format of a key changes we'll
477 // need a new chunk. (I didn't wrap each variable in its own chunk)
479 for (int i=0; i<keycount; i++) {
480 csave.Write(&(Keys[i].Point),sizeof(Keys[i].Point));
481 csave.Write(&(Keys[i].Time),sizeof(Keys[i].Time));
482 csave.Write(&(Keys[i].Extra),sizeof(Keys[i].Extra));
483 }
484 csave.End_Chunk();
485 return true;
486}
487
489{
490 int i;
491 int keycount = 0;
492 KeyClass newkey;
493
494 // reset the curve
495 Keys.Delete_All();
496
497 // read in the chunks
498 while (cload.Open_Chunk()) {
499
500 switch(cload.Cur_Chunk_ID())
501 {
503
504 while (cload.Open_Micro_Chunk()) {
505 switch(cload.Cur_Micro_Chunk_ID()) {
508 }
509 cload.Close_Micro_Chunk();
510 }
511 break;
512
514 for (i=0; i<keycount; i++) {
515 cload.Read(&(newkey.Point),sizeof(newkey.Point));
516 cload.Read(&(newkey.Time),sizeof(newkey.Time));
517 cload.Read(&(newkey.Extra),sizeof(newkey.Extra));
518 Keys.Add(newkey);
519 }
520 break;
521
522 default:
523 WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",__FILE__,__LINE__));
524 break;
525 }
526 cload.Close_Chunk();
527 }
528
529 return true;
530}
531
532/***********************************************************************************************
533**
534** LinearCurve1DClass, linearly interpolates the keys
535**
536***********************************************************************************************/
537void LinearCurve1DClass::Evaluate(float time,float * set_val)
538{
539 if (!IsLooping) {
540 if (time < Keys[0].Time) {
541 *set_val = Keys[0].Point;
542 return;
543 }
544
545 if (time >= Keys[Keys.Count() - 1].Time) {
546 *set_val = Keys[Keys.Count() - 1].Point;
547 return;
548 }
549 }
550
551 int i0,i1;
552 float t;
553 Find_Interval(time,&i0,&i1,&t);
554
555 *set_val = Keys[i0].Point + t * (Keys[i1].Point - Keys[i0].Point);
556}
557
562
564{
566 Curve1DClass::Save(csave);
567 csave.End_Chunk();
568 return true;
569}
570
572{
573 while (cload.Open_Chunk()) {
574
575 switch(cload.Cur_Chunk_ID())
576 {
578 Curve1DClass::Load(cload);
579 break;
580
581 default:
582 WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",__FILE__,__LINE__));
583 break;
584 }
585 cload.Close_Chunk();
586 }
587
588 return true;
589}
590
591
#define NULL
Definition BaseType.h:92
#define WWASSERT
@ false
Definition bool.h:59
#define WRITE_MICRO_CHUNK(csave, id, var)
Definition chunkio.h:293
#define READ_MICRO_CHUNK(cload, id, var)
Definition chunkio.h:334
bool Close_Micro_Chunk()
Definition chunkio.cpp:585
bool Close_Chunk()
Definition chunkio.cpp:448
uint32 Cur_Chunk_ID()
Definition chunkio.cpp:484
uint32 Cur_Micro_Chunk_ID()
Definition chunkio.cpp:622
uint32 Read(void *buf, uint32 nbytes)
Definition chunkio.cpp:692
bool Open_Chunk()
Definition chunkio.cpp:412
bool Open_Micro_Chunk()
Definition chunkio.cpp:557
uint32 Write(const void *buf, uint32 nbytes)
Definition chunkio.cpp:264
bool Begin_Chunk(uint32 id)
Definition chunkio.cpp:108
bool End_Chunk()
Definition chunkio.cpp:148
unsigned int Extra
Definition curve.h:157
float Get_Start_Time(void)
Definition curve.cpp:361
virtual void Clear_Keys(void)
Definition curve.cpp:431
virtual bool Is_Looping(void)
Definition curve.cpp:351
void Find_Interval(float time, int *i0, int *i1, float *t)
Definition curve.cpp:436
virtual int Key_Count(void)
Definition curve.cpp:379
virtual void Get_Key(int i, float *set_point, float *set_t, unsigned int *extra=NULL)
Definition curve.cpp:384
virtual bool Load(ChunkLoadClass &cload)
Definition curve.cpp:488
bool IsLooping
Definition curve.h:162
virtual void Set_Key(int i, float point, unsigned int extra=0)
Definition curve.cpp:399
Curve1DClass(void)
Definition curve.cpp:330
virtual int Add_Key(float point, float t, unsigned int extra=0)
Definition curve.cpp:408
virtual void Remove_Key(int i)
Definition curve.cpp:424
float Get_End_Time(void)
Definition curve.cpp:370
Curve1DClass & operator=(const Curve1DClass &that)
Definition curve.cpp:344
virtual bool Save(ChunkSaveClass &csave)
Definition curve.cpp:468
virtual ~Curve1DClass(void)
Definition curve.cpp:340
DynamicVectorClass< KeyClass > Keys
Definition curve.h:163
virtual void Set_Looping(bool onoff)
Definition curve.cpp:356
Curve3DClass(void)
Definition curve.cpp:87
virtual void Remove_Key(int i)
Definition curve.cpp:176
virtual void Clear_Keys(void)
Definition curve.cpp:183
virtual void Set_Key(int i, const Vector3 &point)
Definition curve.cpp:153
bool IsLooping
Definition curve.h:103
virtual int Key_Count(void)
Definition curve.cpp:136
void Find_Interval(float time, int *i0, int *i1, float *t)
Definition curve.cpp:188
virtual bool Load(ChunkLoadClass &cload)
Definition curve.cpp:221
Curve3DClass & operator=(const Curve3DClass &that)
Definition curve.cpp:101
virtual ~Curve3DClass(void)
Definition curve.cpp:97
float Get_Start_Time(void)
Definition curve.cpp:118
float Get_End_Time(void)
Definition curve.cpp:127
virtual void Set_Looping(bool onoff)
Definition curve.cpp:113
virtual bool Is_Looping(void)
Definition curve.cpp:108
virtual bool Save(ChunkSaveClass &csave)
Definition curve.cpp:202
virtual void Get_Key(int i, Vector3 *set_point, float *set_t)
Definition curve.cpp:141
virtual int Add_Key(const Vector3 &point, float t)
Definition curve.cpp:161
DynamicVectorClass< KeyClass > Keys
Definition curve.h:104
virtual bool Save(ChunkSaveClass &csave)
Definition curve.cpp:563
virtual void Evaluate(float time, float *set_val)
Definition curve.cpp:537
virtual const PersistFactoryClass & Get_Factory(void) const
Definition curve.cpp:558
virtual bool Load(ChunkLoadClass &cload)
Definition curve.cpp:571
virtual const PersistFactoryClass & Get_Factory(void) const
Definition curve.cpp:291
virtual void Evaluate(float time, Vector3 *set_val)
Definition curve.cpp:272
virtual bool Save(ChunkSaveClass &csave)
Definition curve.cpp:296
virtual bool Load(ChunkLoadClass &cload)
Definition curve.cpp:304
SimplePersistFactoryClass< LinearCurve1DClass, WWMATH_CHUNKID_LINEARCURVE1D > _LinearCurve1DFactory
Definition curve.cpp:55
SimplePersistFactoryClass< LinearCurve3DClass, WWMATH_CHUNKID_LINEARCURVE3D > _LinearCurve3DFactory
Definition curve.cpp:54
@ CURVE1D_CHUNK_VARIABLES
Definition curve.cpp:70
@ CURVE3D_CHUNK_VARIABLES
Definition curve.cpp:60
@ CURVE1D_VARIABLE_KEYCOUNT
Definition curve.cpp:74
@ LINEARCURVE1D_CHUNK_CURVE1D
Definition curve.cpp:77
@ CURVE3D_CHUNK_KEYS
Definition curve.cpp:61
@ CURVE3D_VARIABLE_ISLOOPING
Definition curve.cpp:63
@ CURVE3D_VARIABLE_KEYCOUNT
Definition curve.cpp:64
@ CURVE1D_CHUNK_KEYS
Definition curve.cpp:71
@ LINEARCURVE3D_CHUNK_CURVE3D
Definition curve.cpp:67
@ CURVE1D_VARIABLE_ISLOOPING
Definition curve.cpp:73
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114
#define DECLARE_FORCE_LINK(module)
Definition wwhack.h:48