Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
cardinalspline.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:: /Commando/Code/wwmath/cardinalspline.cpp $*
26 * *
27 * Author:: Greg Hjelstrom *
28 * *
29 * $Modtime:: 9/16/01 4:07p $*
30 * *
31 * $Revision:: 6 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37
38#include "cardinalspline.h"
39#include "wwdebug.h"
40#include "persistfactory.h"
41#include "wwmathids.h"
42#include "wwhack.h"
43
44/*
45** Force-Link this module because the linker can't detect that we actually need it...
46*/
47DECLARE_FORCE_LINK(cardinalspline);
48
49
50/*
51** Save-Load stuff
52*/
55
56enum
57{
58 // ID's used by CardinalSpline3D
61
62 // ID's used by CardinalSpline1D
65};
66
67
68/*
69** CardinalSpline3DClass Implementation
70*/
71int CardinalSpline3DClass::Add_Key(const Vector3 & point,float t)
72{
73 int index = HermiteSpline3DClass::Add_Key(point,t);
74 float tightness = 0.5f;
75 Tightness.Insert(index,tightness);
76 return index;
77}
78
84
90
91void CardinalSpline3DClass::Set_Tightness(int i,float tightness)
92{
93 WWASSERT(i >= 0);
94 WWASSERT(i < Tightness.Count());
95 Tightness[i] = tightness;
96 TangentsDirty = true;
97}
98
100{
101 return Tightness[i];
102}
103
105{
106 if (Keys.Count() < 2) {
107 for (int i=0; i<Keys.Count(); i++) {
108 Tangents[0].InTangent.Set(0,0,0);
109 Tangents[0].OutTangent.Set(0,0,0);
110 }
111 return;
112 }
113
114 // First and Last Key:
115 // Only need to compute the OutTangent for key[0] and the InTangent for key[end]
116 int end = Keys.Count() - 1;
117 Tangents[0].InTangent.Set(0,0,0);
118 Tangents[end].OutTangent.Set(0,0,0);
119
120 if (IsLooping) {
121
122 // This really only works if the start and end points have the same position...
123 Tangents[0].OutTangent.X = (1.0f - Tightness[0])*(Keys[1].Point.X - Keys[end-1].Point.X);
124 Tangents[0].OutTangent.Y = (1.0f - Tightness[0])*(Keys[1].Point.Y - Keys[end-1].Point.Y);
125 Tangents[0].OutTangent.Z = (1.0f - Tightness[0])*(Keys[1].Point.Z - Keys[end-1].Point.Z);
126 Tangents[end].InTangent = Tangents[0].OutTangent;
127
128 } else {
129
130 Tangents[0].OutTangent.X = (1.0f - Tightness[0])*(Keys[1].Point.X - Keys[0].Point.X);
131 Tangents[0].OutTangent.Y = (1.0f - Tightness[0])*(Keys[1].Point.Y - Keys[0].Point.Y);
132 Tangents[0].OutTangent.Z = (1.0f - Tightness[0])*(Keys[1].Point.Z - Keys[0].Point.Z);
133
134 Tangents[end].InTangent.X = (1.0f - Tightness[0])*(Keys[end].Point.X - Keys[end-1].Point.X);
135 Tangents[end].InTangent.Y = (1.0f - Tightness[0])*(Keys[end].Point.Y - Keys[end-1].Point.Y);
136 Tangents[end].InTangent.Z = (1.0f - Tightness[0])*(Keys[end].Point.Z - Keys[end-1].Point.Z);
137
138 }
139
140 float total_time = (Keys[1].Time - Keys[0].Time) + (Keys[end].Time - Keys[end-1].Time);
141 float in_factor = 2.0f * (Keys[end].Time - Keys[end-1].Time) / total_time;
142 float out_factor = 2.0f * (Keys[1].Time - Keys[0].Time) / total_time;
143 Tangents[end].InTangent *= in_factor;
144 Tangents[0].OutTangent *= out_factor;
145
146
147 // inner knots
148 for (int i=1; i<Keys.Count()-1; i++) {
149 Tangents[i].InTangent.X = (1.0f - Tightness[i])*(Keys[i+1].Point.X - Keys[i-1].Point.X);
150 Tangents[i].InTangent.Y = (1.0f - Tightness[i])*(Keys[i+1].Point.Y - Keys[i-1].Point.Y);
151 Tangents[i].InTangent.Z = (1.0f - Tightness[i])*(Keys[i+1].Point.Z - Keys[i-1].Point.Z);
152 Tangents[i].OutTangent = Tangents[i].InTangent;
153
154 float in_factor = 2.0f * (Keys[i].Time - Keys[i-1].Time) / (Keys[i+1].Time - Keys[i-1].Time);
155 float out_factor = 2.0f * (Keys[i+1].Time - Keys[i].Time) / (Keys[i+1].Time - Keys[i-1].Time);
156
157 Tangents[i].InTangent *= in_factor; // compensating for the un-even keys
158 Tangents[i].OutTangent *= out_factor;
159 }
160 TangentsDirty = false;
161}
162
167
169{
172 csave.End_Chunk();
173
175 for (int i=0; i<Tightness.Count(); i++) {
176 float tightness = Tightness[i];
177 csave.Write(&(tightness),sizeof(tightness));
178 }
179 csave.End_Chunk();
180 return true;
181}
182
184{
185 int i;
186 float tightness;
187
188 // reset the array of tightness keys
189 Tightness.Delete_All();
190
191 // read in the chunks
192 while (cload.Open_Chunk()) {
193
194 switch(cload.Cur_Chunk_ID())
195 {
198 break;
199
201 for (i=0; i<Keys.Count(); i++) {
202 cload.Read(&(tightness),sizeof(tightness));
203 Tightness.Add(tightness);
204 }
205 break;
206
207 default:
208 WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",__FILE__,__LINE__));
209 break;
210 }
211 cload.Close_Chunk();
212 }
213
214 return true;
215}
216
217
218/*
219** CardinalSpline1DClass Implementation
220*/
221int CardinalSpline1DClass::Add_Key(float point,float t)
222{
223 int index = HermiteSpline1DClass::Add_Key(point,t);
224 float tightness = 0.5f;
225 Tightness.Insert(index,tightness);
226 return index;
227}
228
234
240
241void CardinalSpline1DClass::Set_Tightness(int i,float tightness)
242{
243 WWASSERT(i >= 0);
244 WWASSERT(i < Tightness.Count());
245 Tightness[i] = tightness;
246 TangentsDirty = true;
247}
248
250{
251 return Tightness[i];
252}
253
255{
256 if (Keys.Count() < 2) {
257 for (int i=0; i<Keys.Count(); i++) {
258 Tangents[0].InTangent = 0;
259 Tangents[0].OutTangent = 0;
260 }
261 }
262
263 // First and Last Key:
264 // Only need to compute the OutTangent for key[0] and the InTangent for key[end]
265 int end = Keys.Count() - 1;
266 Tangents[0].InTangent = 0;
267 Tangents[end].OutTangent = 0;
268
269 if (IsLooping) {
270
271 // This really only works if the start and end points have the same position...
272 Tangents[0].OutTangent = (1.0f - Tightness[0])*(Keys[1].Point - Keys[end-1].Point);
273 Tangents[end].InTangent = Tangents[0].OutTangent;
274
275 } else {
276
277 Tangents[0].OutTangent = (1.0f - Tightness[0])*(Keys[1].Point - Keys[0].Point);
278 Tangents[end].InTangent = (1.0f - Tightness[0])*(Keys[end].Point - Keys[end-1].Point);
279 }
280
281 float total_time = (Keys[1].Time - Keys[0].Time) + (Keys[end].Time - Keys[end-1].Time);
282 float in_factor = 2.0f * (Keys[end].Time - Keys[end-1].Time) / total_time;
283 float out_factor = 2.0f * (Keys[1].Time - Keys[0].Time) / total_time;
284 Tangents[end].InTangent *= in_factor;
285 Tangents[0].OutTangent *= out_factor;
286
287
288 // inner knots
289 for (int i=1; i<Keys.Count()-1; i++) {
290 Tangents[i].InTangent = (1.0f - Tightness[i])*(Keys[i+1].Point - Keys[i-1].Point);
291 Tangents[i].OutTangent = Tangents[i].InTangent;
292
293 float in_factor = 2.0f * (Keys[i].Time - Keys[i-1].Time) / (Keys[i+1].Time - Keys[i-1].Time);
294 float out_factor = 2.0f * (Keys[i+1].Time - Keys[i].Time) / (Keys[i+1].Time - Keys[i-1].Time);
295
296 Tangents[i].InTangent *= in_factor; // compensating for the un-even keys
297 Tangents[i].OutTangent *= out_factor;
298 }
299 TangentsDirty = false;
300}
301
306
308{
311 csave.End_Chunk();
312
314 for (int i=0; i<Tightness.Count(); i++) {
315 float tightness = Tightness[i];
316 csave.Write(&(tightness),sizeof(tightness));
317 }
318 csave.End_Chunk();
319 return true;
320}
321
323{
324 int i;
325 float tightness;
326
327 // reset the array of tangents
328 Tightness.Delete_All();
329
330 // read in the chunks
331 while (cload.Open_Chunk()) {
332
333 switch(cload.Cur_Chunk_ID())
334 {
337 break;
338
340 for (i=0; i<Keys.Count(); i++) {
341 cload.Read(&(tightness),sizeof(tightness));
342 Tightness.Add(tightness);
343 }
344 break;
345
346 default:
347 WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",__FILE__,__LINE__));
348 break;
349 }
350 cload.Close_Chunk();
351 }
352
353 return true;
354}
355
356
#define WWASSERT
SimplePersistFactoryClass< CardinalSpline3DClass, WWMATH_CHUNKID_CARDINALSPLINE3D > _CardinalSpline3DFactory
@ CARDINAL3D_CHUNK_HERMITE3D
@ CARDINAL1D_CHUNK_HERMITE1D
@ CARDINAL3D_CHUNK_TIGHTNESSKEYS
@ CARDINAL1D_CHUNK_TIGHTNESSKEYS
SimplePersistFactoryClass< CardinalSpline1DClass, WWMATH_CHUNKID_CARDINALSPLINE1D > _CardinalSpline1DFactory
virtual void Clear_Keys(void)
virtual bool Load(ChunkLoadClass &cload)
virtual int Add_Key(float point, float t)
virtual bool Save(ChunkSaveClass &csave)
DynamicVectorClass< float > Tightness
virtual void Update_Tangents(void)
virtual void Set_Tightness(int i, float tightness)
virtual float Get_Tightness(int i)
virtual const PersistFactoryClass & Get_Factory(void) const
virtual void Remove_Key(int i)
virtual void Clear_Keys(void)
virtual void Set_Tightness(int i, float tightness)
virtual void Remove_Key(int i)
virtual bool Load(ChunkLoadClass &cload)
virtual int Add_Key(const Vector3 &point, float t)
virtual float Get_Tightness(int i)
virtual bool Save(ChunkSaveClass &csave)
virtual const PersistFactoryClass & Get_Factory(void) const
DynamicVectorClass< float > Tightness
virtual void Update_Tangents(void)
bool Close_Chunk()
Definition chunkio.cpp:448
uint32 Cur_Chunk_ID()
Definition chunkio.cpp:484
uint32 Read(void *buf, uint32 nbytes)
Definition chunkio.cpp:692
bool Open_Chunk()
Definition chunkio.cpp:412
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
bool IsLooping
Definition curve.h:162
DynamicVectorClass< KeyClass > Keys
Definition curve.h:163
bool IsLooping
Definition curve.h:103
DynamicVectorClass< KeyClass > Keys
Definition curve.h:104
DynamicVectorClass< TangentsClass > Tangents
virtual int Add_Key(float point, float t, unsigned int extra=0)
virtual void Clear_Keys(void)
virtual bool Load(ChunkLoadClass &cload)
virtual bool Save(ChunkSaveClass &csave)
virtual void Remove_Key(int i)
virtual bool Save(ChunkSaveClass &csave)
virtual void Remove_Key(int i)
virtual void Clear_Keys(void)
virtual bool Load(ChunkLoadClass &cload)
DynamicVectorClass< TangentsClass > Tangents
virtual int Add_Key(const Vector3 &point, float t)
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114
#define DECLARE_FORCE_LINK(module)
Definition wwhack.h:48