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 }