Main Page Class Hierarchy Compound List File List Compound Members File Members

Animation.cc

Go to the documentation of this file.
00001 /*
00002 File: Animation.cc
00003 
00004 Function: 
00005 
00006 Author: Andrew Willmott
00007 
00008 Notes: 
00009 */
00010 
00011 #include "gcl/Animation.h"
00012 // XXX
00013 #include "GCLApp.h"
00014 #include "gcl/GCLConfig.h"
00015 
00016  #define DBG_COUT if (0) cerr
00017 
00018 
00019  Void AnimRec::AddKey(GCLReal time, GCLReal value, GCLReal vIn, GCLReal vOut)
00020 {
00021 keyTimes.Append(time);
00022 values.Append(value);
00023 velIn.Append(vIn);
00024 velOut.Append(vOut);
00025 }
00026 
00027  Void AnimRec::SetupAnim()
00028 {
00029 Int i, n = keyTimes.NumItems();
00030 GCLReal autoVel;
00031 
00032 // fill in automatic velocities
00033 
00034 if (n <= 1)
00035 return;
00036 
00037 autoVel = (values[1] - values[0]) / (keyTimes[1] - keyTimes[0]);
00038 if (velIn[0] == kAutoVel)
00039 velIn[0] = autoVel;
00040 if (velOut[0] == kAutoVel)
00041 velOut[0] = autoVel;
00042 
00043 for (i = 1; i < keyTimes.NumItems() - 1; i++)
00044 {
00045 autoVel = (values[i + 1] - values[i - 1]) / (keyTimes[i + 1] - keyTimes[i - 1]);
00046 
00047 if (velIn[i] == kAutoVel)
00048 velIn[i] = autoVel;
00049 if (velOut[i] == kAutoVel)
00050 velOut[i] = autoVel;
00051 }
00052 
00053 autoVel = (values[n - 1] - values[n - 2]) / (keyTimes[n - 1] - keyTimes[n - 2]);
00054 if (velIn[n - 1] == kAutoVel)
00055 velIn[n - 1] = autoVel;
00056 if (velOut[n - 1] == kAutoVel)
00057 velOut[n - 1] = autoVel;
00058 }
00059 
00060  Int AnimRec::FindTimeIndex(GCLReal time)
00061 {
00062 Int i = 0;
00063 
00064 if (currentTimeIndex >= 0 && time > keyTimes[currentTimeIndex])
00065 i = currentTimeIndex + 1;
00066 while (i < keyTimes.NumItems() && time > keyTimes[i])
00067 i++;
00068 
00069 return(i - 1);
00070 }
00071 
00072  GCLReal AnimRec::GetValue(GCLReal time)
00073 {
00074 Int i;
00075 GCLReal t1, t2, y1, y2, s1, s2;
00076 
00077 Assert(keyTimes.NumItems() > 0, "(AnimRec::GetValue) must have at least one keyframe");
00078 
00079 i = FindTimeIndex(time);
00080 
00081 if (i < 0)
00082 return(values[0]);
00083 if (i >= keyTimes.NumItems() - 1)
00084 return(values[keyTimes.NumItems() - 1]);
00085 
00086 t1 = keyTimes[i];
00087 t2 = keyTimes[i + 1];
00088 
00089 if (i != currentTimeIndex)
00090 {
00091 // recalculate cubic for next bracket
00092 DBG_COUT << "new cubic for t = " << time << endl;
00093 currentTimeIndex = i;
00094 y1 = values[i];
00095 y2 = values[i + 1];
00096 
00097 #ifdef OLD
00098 if (i == 0)
00099 // no prior keyframe
00100 s1 = (y2 - y1) / (t2 - t1);
00101 else
00102 s1 = (y2 - values[i - 1]) / (t2 - keyTimes[i - 1]);
00103 
00104 if (i == keyTimes.NumItems() - 2)
00105 // no posterior keyframe
00106 s2 = (y2 - y1) / (t2 - t1);
00107 else
00108 s2 = (values[i + 2] - y1) / (keyTimes[i + 2] - t1);
00109 #else
00110 s1 = velOut[i];
00111 s2 = velIn[i + 1];
00112 #endif
00113 
00114 CalcHermiteCoeffs(t1, t2, y1, y2, s1, s2, currentCubic);
00115 }
00116 
00117 return(EvalCubic(currentCubic, time, t1, t2));
00118 }
00119 
00120 
00121 // --- Animation class --------------------------------------------------------
00122 
00123 
00124  struct Dumper : IntHashIter
00125 {
00126  Dumper(AnimRecList &a, GCLReal t, Bool ad) : 
00127 recs(a), time(t), addDash(ad) {};
00128 
00129  Void ProcessItem(StrConst s, Int a) 
00130 {
00131 cout << ' ';
00132 if (addDash)
00133 cout << '-';
00134 cout << s << ' ' << recs[a]->GetValue(time);
00135 }
00136 
00137  AnimRecList &recs;
00138  GCLReal time;
00139  Bool addDash;
00140 };
00141 
00142  Void Animation::DumpAvars(GCLReal time, Int frame)
00143 {
00144 Dumper dumper(avarRecs, time, addDash);
00145 
00146 if (!quiet)
00147 {
00148 if (tag)
00149 cout << tag << '_' << frame;
00150 else
00151 cout << "time " << time << " frame " << frame;
00152 }
00153 avarNames.Iterate(dumper);
00154 cout << endl;
00155 }
00156 
00157  GCLReal Animation::GetValue(StrConst avarName, GCLReal time)
00158 {
00159 return(avarRecs[avarNames.GetItem(avarName)]->GetValue(time));
00160 }
00161 
00162  struct CameraUpdater : IntHashIter
00163 {
00164  CameraUpdater(AnimRecList &a, GCLReal t, Camera &c) : 
00165 recs(a), time(t), camera(c) {};
00166 
00167  Void ProcessItem(StrConst s, Int a) 
00168 {
00169 camera.CheckAvar(s, recs[a]->GetValue(time));
00170 }
00171 
00172  AnimRecList &recs;
00173  Camera &camera;
00174  GCLReal time;
00175 };
00176 
00177  Void Animation::SetAvarList(scAvarList *avarList, scCamera *itsCamera, GCLReal time)
00178 {
00179 Int i;
00180 
00181 if (avarMap.NumItems() == 0 && avarList->NumItems() > 0)
00182 {
00183 // build avarMap: maps from avarList entry to to avarRecs entry
00184 
00185 avarMap.SetSize(avarList->NumItems());
00186 for (i = 0; i < avarList->NumItems(); i++)
00187 avarMap[i] = avarNames.GetItem((*avarList)[i].name);
00188 }
00189 
00190 // update avar list
00191 for (i = 0; i < avarList->NumItems(); i++)
00192 if (avarMap[i] >= 0)
00193 (*avarList)[i].value = avarRecs[avarMap[i]]->GetValue(time);
00194 
00195 if (itsCamera)
00196 {
00197 CameraUpdater cu(avarRecs, time, *itsCamera);
00198 
00199 avarNames.Iterate(cu);
00200 
00201 itsCamera->SetupFromParams();
00202 }
00203 }
00204 
00205  Void Animation::AddKey(StrConst avarName, GCLReal time, GCLReal value,
00206 GCLReal velIn, GCLReal velOut)
00207 {
00208 Int i;
00209 
00210 if (!avarNames.ItemExists(avarName))
00211 {
00212 // new avar: create avarRec
00213 
00214 i = avarRecs.NumItems();
00215 avarNames.SetItem(avarName, i);
00216 avarRecs.Append(new AnimRec);
00217 }
00218 else
00219 i = avarNames.GetItem(avarName);
00220 
00221 avarRecs[i]->AddKey(time, value, velIn, velOut);
00222 }
00223 
00241  Bool Animation::ParseAnimFile(StrConst filename)
00242 {
00243 String func;
00244 ifstream s;
00245 
00246 Int lines = 0;
00247 GCLReal currentTime = 0.0;
00248 String avarName, avarVal;
00249 GCLReal value = 0.0;
00250 GCLReal velIn = kAutoVel;
00251 GCLReal velOut = kAutoVel;
00252 GCLReal setVel;
00253 
00254 length = 0.0;
00255 avarRecs.Clear();
00256 
00257 s.open(filename);
00258 if (!s)
00259 {
00260 cerr << "Cannot access " << filename << endl;
00261 return(false);
00262 }
00263 
00264 while (s)
00265 {
00266 if (func.ReadWord(s))
00267 {
00268 lines++;
00269 if (func[0] == '#')
00270 ;
00271 else if (func == "t")
00272 {
00273 s >> currentTime;
00274 length = Max(length, currentTime);
00275 // reset velocities to auto
00276 velIn = velOut = kAutoVel;
00277 }
00278 else if (func == "dt")
00279 {
00280 GCLReal delta;
00281 
00282 s >> delta;
00283 currentTime += delta;
00284 length = Max(length, currentTime);
00285 // reset velocities to auto
00286 velIn = velOut = kAutoVel;
00287 }
00288 else if (func == "k")
00289 {
00290 avarName.ReadWord(s);
00291 
00292 if (avarName.Suffix(2) == "_q")
00293 {
00294 String stub = avarName.Prefix(-2);
00295 
00296 avarName.Printf("%s_x", stub.CString());
00297 s >> value;
00298 AddKey(avarName, currentTime, value, velIn, velOut);
00299 
00300 avarName.Printf("%s_y", stub.CString());
00301 s >> value;
00302 AddKey(avarName, currentTime, value, velIn, velOut);
00303 
00304 avarName.Printf("%s_z", stub.CString());
00305 s >> value;
00306 AddKey(avarName, currentTime, value, velIn, velOut);
00307 
00308 avarName.Printf("%s_w", stub.CString());
00309 s >> value;
00310 AddKey(avarName, currentTime, value, velIn, velOut);
00311 }
00312 else if (avarName.Suffix(2) == "_v")
00313 {
00314 String stub = avarName.Prefix(-2);
00315 
00316 avarName.Printf("%s_x", stub.CString());
00317 s >> value;
00318 AddKey(avarName, currentTime, value, velIn, velOut);
00319 
00320 avarName.Printf("%s_y", stub.CString());
00321 s >> value;
00322 AddKey(avarName, currentTime, value, velIn, velOut);
00323 
00324 avarName.Printf("%s_z", stub.CString());
00325 s >> value;
00326 AddKey(avarName, currentTime, value, velIn, velOut);
00327 }
00328 else if (avarName.Suffix(2) == "_c")
00329 {
00330 String stub = avarName.Prefix(-2);
00331 
00332 avarName.Printf("%s_x", stub.CString());
00333 s >> value;
00334 AddKey(avarName, currentTime, value, velIn, velOut);
00335 
00336 avarName.Printf("%s_y", stub.CString());
00337 s >> value;
00338 AddKey(avarName, currentTime, value, velIn, velOut);
00339 }
00340 else
00341 {
00342 s >> value;
00343 AddKey(avarName, currentTime, value, velIn, velOut);
00344 }
00345 }
00346 else if (func[0] == 'v')
00347 {
00348 avarVal.ReadWord(s);
00349 if (avarVal == "auto")
00350 setVel = kAutoVel;
00351 else
00352 setVel = atof(avarVal.CString());
00353 
00354 if (func == "v")
00355 velOut = velIn = setVel;
00356 else if (func == "vi")
00357 velIn = setVel;
00358 else if (func == "vo")
00359 velOut = setVel;
00360 }
00361 else
00362 cerr << "(ParseAnimFile) *** Ignoring unknown token: " << func << endl;
00363 
00364 func.ReadLine(s); // ignore rest of line
00365 }
00366 }
00367 
00368 for (Int i = 0; i < avarRecs.NumItems(); i++)
00369 avarRecs[i]->SetupAnim();
00370 
00371 return(true);
00372 }

Generated at Sat Aug 5 00:16:56 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000

AltStyle によって変換されたページ (->オリジナル) /