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