My Project
IAnimated.h
1 #pragma once
2 
3 namespace ParaEngine
4 {
5  class Quaternion;
6 
7  enum Interpolations {
8  INTERPOLATION_NONE,
9  INTERPOLATION_LINEAR,
10  INTERPOLATION_HERMITE,
11  // only use linear interpolation cross frames. a frame is assumed to be 1/30 seconds in the Engine. If two key frames are this close to each other, no interpolation is used.
12  // this is the default setting for UV translation animations.
13  INTERPOLATION_LINEAR_CROSSFRAME,
14  };
15 
16 
18  class IAnimated
19  {
20  public:
21  virtual ~IAnimated(){};
22 
24  virtual int GetNumKeys();
26  virtual void SetNumKeys(int nKeyCount);
27 
31  virtual int GetNextKeyIndex(int nTime);
32 
38  virtual int AddKey(int time, bool* isKeyExist = NULL);
39 
44  virtual void SetTime(int nIndex, int nTime);
45  virtual int GetTime(int nIndex);
46 
47  virtual void SetValue(int nIndex, const Quaternion& val);
48  virtual bool GetValue(int nIndex, Quaternion& val);
49  virtual bool GetValueByTime(int nTime, Quaternion& val);
50 
51  virtual void SetValue(int nIndex, const Vector2& val);
52  virtual bool GetValue(int nIndex, Vector2& val);
53  virtual bool GetValueByTime(int nTime, Vector2& val);
54 
55  virtual void SetValue(int nIndex, const Vector3& val);
56  virtual bool GetValue(int nIndex, Vector3& val);
57  virtual bool GetValueByTime(int nTime, Vector3& val);
58 
59  virtual void SetValue(int nIndex, const double& val);
60  virtual bool GetValue(int nIndex, double& val);
61  virtual bool GetValueByTime(int nTime, double& val);
62 
63  virtual void SetValue(int nIndex, const float& val);
64  virtual bool GetValue(int nIndex, float& val);
65  virtual bool GetValueByTime(int nTime, float& val);
66 
67  virtual void SetValue(int nIndex, const int& val);
68  virtual bool GetValue(int nIndex, int& val);
69  virtual bool GetValueByTime(int nTime, int& val);
70 
71  virtual void SetValue(int nIndex, const std::string& val);
72  virtual bool GetValue(int nIndex, std::string& val);
73  virtual bool GetValueByTime(int nTime, std::string& val);
74  };
75 
76 
77  // interpolation functions
78  template<class T>
79  inline T interpolate(const float r, const T &v1, const T &v2)
80  {
81  return (v1*(1.0f - r) + v2*r);
82  }
83 
84  template<class T>
85  inline T interpolateHermite(const float r, const T &v1, const T &v2, const T &in, const T &out)
86  {
87  // dummy
88  //return interpolate<T>(r,v1,v2);
89 
90  // basis functions
91  float h1 = 2.0f*r*r*r - 3.0f*r*r + 1.0f;
92  float h2 = -2.0f*r*r*r + 3.0f*r*r;
93  float h3 = r*r*r - 2.0f*r*r + r;
94  float h4 = r*r*r - r*r;
95 
96  // interpolation
97  return static_cast<T>(v1*h1 + v2*h2 + in*h3 + out*h4);
98  }
99 
100  // "linear" interpolation for quaternions should be slerp by default
101  template<>
102  inline Quaternion interpolate<Quaternion>(const float r, const Quaternion &v1, const Quaternion &v2)
103  {
104  return Quaternion::Slerp(r, v1, v2, true);
105  }
106 
107  // Convert opacity values stored as shorts to floating point
108  class ShortToFloat {
109  public:
110  inline static const float conv(const DWORD t)
111  {
112  return t / 32767.0f;
113  }
114  };
115 
116  template <class T>
117  class Identity {
118  public:
119  inline static const T& conv(const T& t)
120  {
121  return t;
122  }
123  };
124 
126  template <class T, class Conv = Identity<T> >
128  {
129  public:
130  AnimatedVariable() : m_interpolationType(INTERPOLATION_LINEAR){
131  };
132  virtual ~AnimatedVariable(){};
133  public:
137  virtual bool GetValueByTime(int time, T& val)
138  {
139  int nNumKeys = (int) m_data.size();
140  if (nNumKeys > 1)
141  {
142  size_t pos = 0;
143 
144  int nStart = 0;
145  int nEnd = nNumKeys-2;
146  while (true)
147  {
148  if (nStart >= nEnd)
149  { // if no item left.
150  pos = nStart;
151  break;
152  }
153  int nMid = (nStart + nEnd) / 2;
154  int startP = (m_times[nMid]);
155  int endP = (m_times[nMid + 1]);
156 
157  if (startP <= time && time < endP)
158  { // if (middle item is target)
159  pos = nMid;
160  break;
161  }
162  else if (time < startP)
163  { // if (target < middle item)
164  nEnd = nMid;
165  }
166  else if (time >= endP)
167  { // if (target >= middle item)
168  nStart = nMid + 1;
169  }
170  }// while(nStart<=nEnd)
171 
172  int t1 = m_times[pos];
173  int t2 = m_times[pos + 1];
174  /*if (time > t2 || time < t1)
175  {
176  return false;
177  }*/
178  if (time >= t2)
179  {
180  val = m_data[pos + 1];
181  }
182  else if (time <= t1)
183  {
184  val = m_data[pos];
185  }
186  else
187  {
188  float r = (time - t1) / (float)(t2 - t1);
189 
190  if (m_interpolationType == INTERPOLATION_LINEAR)
191  val = interpolate<T>(r, m_data[pos], m_data[pos + 1]);
192  else if (m_interpolationType == INTERPOLATION_LINEAR_CROSSFRAME)
193  {
194  if ((t2 - t1) <= 34) // if the two key frames are less than 33 milliseconds away, do not interpolate, instead use the first one.
195  val = m_data[pos];
196  else
197  val = interpolate<T>(r, m_data[pos], m_data[pos + 1]);
198  }
199  else {
200  // INTERPOLATION_HERMITE is only used in cameras afraid?
201  // return interpolateHermite<T>(r,data[pos],data[pos+1],in[pos],out[pos]);
202  // TODO: use linear interpolation anyway
203  val = interpolate<T>(r, m_data[pos], m_data[pos + 1]);
204  }
205  }
206  return true;
207  }
208  else if (nNumKeys > 0)
209  {
210  // default value
211  val = m_data[0];
212  return true;
213  }
214  else
215  return false;
216  }
217 
218  virtual bool GetValue(int nIndex, T& val)
219  {
220  if (nIndex < GetNumKeys())
221  {
222  val = m_data[nIndex];
223  return true;
224  }
225  else if (m_data.size() > 0)
226  {
227  val = m_data[m_data.size()-1];
228  return true;
229  }
230  return false;
231  }
232 
233  virtual void SetValue(int nIndex, const T& val)
234  {
235  if (nIndex < GetNumKeys())
236  {
237  m_data[nIndex] = val;
238  }
239  else if (nIndex>=0)
240  {
241  SetNumKeys(nIndex + 1);
242  SetValue(nIndex, val);
243  }
244  }
245 
246  virtual int GetNumKeys()
247  {
248  return (int)m_data.size();
249  }
250 
251  virtual void SetNumKeys(int nKeyCount)
252  {
253  if (GetNumKeys() != nKeyCount)
254  {
255  m_data.resize(nKeyCount);
256  m_times.resize(nKeyCount);
257  }
258  }
259 
260  virtual void SetTime(int nIndex, int nTime)
261  {
262  if (nIndex < (int)m_times.size())
263  m_times[nIndex] = nTime;
264  }
265 
266  virtual int GetTime(int nIndex)
267  {
268  return (nIndex < (int)m_times.size()) ? m_times[nIndex] : 0;
269  }
270 
271  virtual int GetNextKeyIndex(int time)
272  {
273  int dataCount = (int)m_data.size();
274  if (dataCount == 1)
275  {
276  return 0;
277  }
278  else if (dataCount > 0)
279  {
280  int pos = 0;
281 
282  int nStart = 0;
283  int nEnd = dataCount - 1;
284  while (true)
285  {
286  if (nStart >= nEnd)
287  { // if no item left.
288  pos = nStart;
289  break;
290  }
291  int nMid = (nStart + nEnd) / 2;
292  int startP = (m_times[nMid]);
293  int endP = (m_times[nMid + 1]);
294 
295  if (startP <= time && time < endP)
296  { // if (middle item is target)
297  pos = nMid;
298  break;
299  }
300  else if (time < startP)
301  { // if (target < middle item)
302  nEnd = nMid;
303  }
304  else if (time >= endP)
305  { // if (target >= middle item)
306  nStart = nMid + 1;
307  }
308  }// while(nStart<=nEnd)
309 
310  for (int i = pos - 1; i >= 0; --i)
311  {
312  if (m_times[i] >= time)
313  pos = i;
314  else
315  break;
316  }
317  return pos;
318  }
319  return -1;
320  }
321 
322  virtual int AddKey(int time, bool* isKeyExist = NULL)
323  {
324  int index = GetNextKeyIndex(time);
325  if (index < 0)
326  index = 0;
327  if (index < GetNumKeys())
328  {
329  int next_time = GetTime(index);
330  if (next_time == time)
331  {
332  if (isKeyExist)
333  *isKeyExist = true;
334  return index;
335  }
336  else
337  {
338  if (next_time < time)
339  index = index + 1;
340 
341  // insert before next_time;
342  m_times.insert(m_times.begin()+index, time);
343  m_data.insert(m_data.begin()+index, T());
344  if (isKeyExist)
345  *isKeyExist = false;
346  return index;
347  }
348  }
349  else
350  {
351  SetNumKeys(index + 1);
352  if (isKeyExist)
353  *isKeyExist = false;
354  return index;
355  }
356  }
357  private:
359  int m_interpolationType;
360  std::vector<int> m_times;
361  std::vector<T> m_data;
362  };
363 }
virtual int AddKey(int time, bool *isKeyExist=NULL)
add a given key with default value at specified time if there is already a key at the index...
Definition: IAnimated.cpp:26
virtual void SetNumKeys(int nKeyCount)
get set the total number of animated keys.
Definition: IAnimated.h:251
virtual int GetNextKeyIndex(int time)
return the index of the first key whose time is larger than or equal to time.
Definition: IAnimated.h:271
different physics engine has different winding order.
Definition: EventBinding.h:32
Implementation of a Quaternion, i.e.
Definition: ParaQuaternion.h:10
virtual void SetTime(int nIndex, int nTime)
only applied to Animated attribute
Definition: IAnimated.cpp:31
Standard 3-dimensional vector.
Definition: ParaVector3.h:16
virtual int AddKey(int time, bool *isKeyExist=NULL)
add a given key with default value at specified time if there is already a key at the index...
Definition: IAnimated.h:322
Definition: IAnimated.h:117
Standard 2-dimensional vector.
Definition: ParaVector2.h:16
Definition: IAnimated.h:108
base class for AnimatedVariable.
Definition: IAnimated.h:18
key, value pairs
Definition: IAnimated.h:127
virtual bool GetValueByTime(int time, T &val)
this function will return the interpolated animation vector frame number internally use binary search...
Definition: IAnimated.h:137
virtual int GetNumKeys()
get total number of animated keys.
Definition: IAnimated.cpp:11
virtual void SetTime(int nIndex, int nTime)
only applied to Animated attribute
Definition: IAnimated.h:260
virtual void SetNumKeys(int nKeyCount)
get set the total number of animated keys.
Definition: IAnimated.cpp:16
virtual int GetNumKeys()
get total number of animated keys.
Definition: IAnimated.h:246
virtual int GetNextKeyIndex(int nTime)
return the index of the first key whose time is larger than or equal to time.
Definition: IAnimated.cpp:21