Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/particles/quick_animation.cc @ 8096

Last change on this file since 8096 was 7335, checked in by bensch, 19 years ago

orxonox/trunk: adding the same Key with the same Position multiple times does not work anymore (as it should)

File size: 8.9 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: ...
13   co-programmer: ...
14*/
15
16//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
17
18#include "quick_animation.h"
19
20#include <algorithm>
21
22using namespace std;
23
24/**
25 * @brief standard constructor
26 * @param resolution the Resolution of the LookupTable
27 */
28QuickAnimation::QuickAnimation (unsigned int resolution)
29{
30  this->lookupValues.resize(resolution, 0.0f);
31}
32
33/**
34 * @brief deletes all the deconstructor stuff
35 */
36QuickAnimation::~QuickAnimation ()
37{ }
38
39/**
40 * @brief adds a new entry to the list of keyframes
41 * @param position the position to add the key to
42 * @param value the Value to set for the position
43 * @returns false if the key existed already for a given position
44 */
45bool QuickAnimation::addKey(float position, float value)
46{
47  if (position > 1.0f || position < 0.0f)
48  {
49    printf("QuickAnimation::Position MUST BE between 0.0f and 1.0f\n");
50    return false;
51  }
52  if(std::find(this->keyFrames.begin(), this->keyFrames.end(), position) != this->keyFrames.end())
53  {
54    printf("QuickAnimation:: key at position %f already added. Use changeValue instead\n", position);
55    return false;
56  }
57  this->keyFrames.push_back(QuickKeyFrame(position, value));
58
59  this->rebuild();
60  return true;
61}
62
63
64/**
65 * @brief changes an entry in the region of position
66 * @param position the Position of an existing keyframe
67 * @param region a deviation of the existing keyframe (like a delta in witch to search for)
68 * @param value the new Value
69 */
70bool QuickAnimation::changeValueKey(unsigned int keyFrameNumber, float newValue)
71{
72  if (keyFrameNumber < this->keyFrames.size())
73  {
74    this->keyFrames[keyFrameNumber].value = newValue;
75    this->rebuild();
76    return true;
77  }
78  else
79    return false;
80}
81
82/**
83 * @brief changes an entry in the region of position
84 * @param position the Position of an existing keyframe
85 * @param region a deviation of the existing keyframe (like a delta in witch to search for)
86 * @param value the new Value
87 *
88 * This Function adds a new KeyFrame at position with newValue, if none was found in region of position.
89 */
90bool QuickAnimation::changeValue(float position, float newValue, float region)
91{
92  int keyFrame = this->getKeyAt(position, region);
93  if (keyFrame == -1)
94    return this->addKey(position, newValue);
95  else
96    return this->changeValueKey(keyFrame, newValue);
97}
98
99
100/**
101 * @brief removes the keyFrameNumber'th entry.
102 * @param keyFrameNumber the n'th Keyframe to remove.
103 * @returns true on success, false if keyFrameNumber did not exist.
104 */
105bool QuickAnimation::removeKey(unsigned int keyFrameNumber)
106{
107  if (keyFrameNumber < this->keyFrames.size())
108  {
109    this->keyFrames.erase(this->keyFrames.begin() + keyFrameNumber);
110    this->rebuild();
111    return true;
112  }
113  else
114    return false;
115}
116
117
118/**
119 * @brief removes a KeyFrame from the List.
120 * @param position the Keyframe at position position will be erased.
121 * @param region a deviation of the existing keyframe (like a delta in witch to search for)
122 * @returns true on success, false if no KeyFrame was found.
123 */
124bool QuickAnimation::remove(float position, float region)
125{
126  int keyFrame = this->getKeyAt(position, region);
127  if (keyFrame == -1)
128    return false;
129  else
130    return this->removeKey(keyFrame);
131}
132
133/**
134 * @brief moves the keyFrame keyFrameNumber to newPosition/newValue.
135 * @param keyFrameNumber the n'th KeyFrame to move.
136 * @param newPosition the new Position for the KeyFrame.
137 * @param newValue the new Value for the KeyFrame.
138 * @returns true on success, false if the KeyFrame did not exist.
139 */
140bool QuickAnimation::moveKey(unsigned int keyFrameNumber, float newPosition, float newValue)
141{
142  if (keyFrameNumber < this->keyFrames.size())
143  {
144    this->keyFrames[keyFrameNumber].position = newPosition;
145    this->keyFrames[keyFrameNumber].value = newValue;
146    this->rebuild();
147    return true;
148  }
149  else
150    return false;
151}
152
153/**
154 * @brief moves the keyFrame keyFrameNumber to newPosition/value.
155 * @param keyFrameNumber the n'th KeyFrame to move.
156 * @param newPosition the new Position for the KeyFrame.
157 * @returns true on success, false if the KeyFrame did not exist.
158 */
159bool QuickAnimation::moveKey(unsigned int keyFrameNumber, float newPosition)
160{
161  if (keyFrameNumber < this->keyFrames.size())
162  {
163    this->keyFrames[keyFrameNumber].position = newPosition;
164    this->rebuild();
165    return true;
166  }
167  else
168    return false;
169}
170
171/**
172 * @brief moves the keyFrame in the region of oldPosition to newPosition/newValue.
173 * @param oldPosition the old Position for the KeyFrame.
174 * @param newPosition the new Position for the KeyFrame.
175 * @param newValue the new Value for the KeyFrame.
176 * @param region the region around oldPosition to search for the KeyFrame.
177 * @returns true on success, false if the KeyFrame was not found within the region of oldPosition.
178 */
179bool QuickAnimation::move(float oldPosition, float newPosition, float newValue, float region)
180{
181  int keyFrame = this->getKeyAt(oldPosition, region);
182  if (keyFrame == -1)
183    return false;
184  else
185    return this->moveKey(keyFrame, newPosition, newValue);
186}
187
188/**
189 * @brief moves the keyFrame in the region of oldPosition to newPosition/Value.
190 * @param oldPosition the old Position for the KeyFrame.
191 * @param newPosition the new Position for the KeyFrame.
192 * @param region the region around oldPosition to search for the KeyFrame.
193 * @returns true on success, false if the KeyFrame was not found within the region of oldPosition.
194 */
195bool QuickAnimation::move(float oldPosition, float newPosition, float region)
196{
197  int keyFrame = this->getKeyAt(oldPosition, region);
198  if (keyFrame == -1)
199    return false;
200  else
201    return this->moveKey(keyFrame, newPosition);
202}
203
204
205/**
206 * @brief searches for a Keyframe in the region of position
207 * @param position the Keyframe at position position will searched for.
208 * @param region a deviation of the existing keyframe (like a delta in witch to search for)
209 * @returns the keyFrame on success, -1 on fault.
210 */
211int QuickAnimation::getKeyAt(float position, float region)
212{
213  for (unsigned int i = 0; i < this->keyFrames.size(); i++)
214  {
215    if (this->keyFrames[i].position + region/2.0 > position && this->keyFrames[i].position - region/2.0 < position)
216      return i;
217  }
218  return -1;
219}
220
221
222/**
223 * @brief rebuilds the QuickAnimation.
224 */
225void QuickAnimation::rebuild()
226{
227  // if we do not have any KeyFrames
228  if (this->keyFrames.empty())
229  {
230    for (unsigned int i = 0; i < this->lookupValues.size(); i++)
231      this->lookupValues[i] = 0.0f;
232    return;
233  }
234
235  // Sort the List.
236  std::sort(this->keyFrames.begin(), this->keyFrames.end(), QuickKeyFrame::sortPositionPredicate);
237
238  // rebuild the lookup-table
239  float sliceSize = 1.0f / this->lookupValues.size();
240  unsigned int key = 0;
241  float preVal = this->keyFrames[0].value;
242  float prePos = this->keyFrames[0].position;
243
244  float postVal = preVal;
245  float postPos = 1.0;
246
247  if (this->keyFrames.size() > 1)
248  {
249    postVal = this->keyFrames[1].value;
250    postPos = this->keyFrames[1].position;
251  }
252
253
254  for (unsigned int i = 0; i < this->lookupValues.size(); i++)
255  {
256    float position = (float)i * sliceSize;
257
258    // if we reach the Next KeyFrame
259    if (position > postPos)
260    {
261      // if we have more KeyFrames.
262      if (this->keyFrames.size() > ++key + 1)
263      {
264        preVal = this->keyFrames[key].value;
265        prePos = this->keyFrames[key].position;
266        postVal = this->keyFrames[key+1].value;
267        postPos = this->keyFrames[key+1].position;
268      }
269      // otherwise we reached the last KeyFrame
270      else
271      {
272        preVal = postVal;
273        prePos = postPos;
274        postPos = 1.0;
275      }
276    }
277    this->lookupValues[i] = preVal + ( postVal - preVal) / (postPos - prePos) * (position - prePos);
278  }
279}
280
281/**
282 * @brief outputs some nice information about this class
283 */
284void QuickAnimation::debug() const
285{
286  printf("QuickAnim(KeyFrames:%d, Resolution:%d)::(position, value) ", this->keyFrames.size(), this->lookupValues.size());
287
288  for (unsigned int i = 0; i < this->keyFrames.size(); i++)
289    printf("(%f, %f)->", this->keyFrames[i].position, this->keyFrames[i].value);
290  printf("\n");
291}
292
293
294
295/**
296 * @brief compares two QuickKeyFrames with their positions.
297 * @param key1 the first keyframe
298 * @param key2 the second keyframe
299 * @returns true, if the key1.position < key2.position.
300 */
301bool QuickAnimation::QuickKeyFrame::sortPositionPredicate(const QuickKeyFrame& key1, const QuickKeyFrame& key2)
302{
303  return (key1.position < key2.position);
304}
305
306/**
307 * @brief compares two QuickKeyFrames with their values.
308 * @param key1 the first keyframe
309 * @param key2 the second keyframe
310 * @returns true, if the key1.value < key2.value.
311 */
312bool QuickAnimation::QuickKeyFrame::sortValuePredicate(const QuickKeyFrame& key1, const QuickKeyFrame& key2)
313{
314  return (key1.value < key2.value);
315}
316
Note: See TracBrowser for help on using the repository browser.