openscenegraph
osgAnimation/Interpolator
Go to the documentation of this file.
1/* -*-c++-*-
2 * Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
3 *
4 * This library is open source and may be redistributed and/or modified under
5 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
6 * (at your option) any later version. The full license is in LICENSE file
7 * included with this distribution, and on the openscenegraph.org website.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * OpenSceneGraph Public License for more details.
13 *
14 * Authors:
15 * Cedric Pinson <cedric.pinson@plopbyte.net>
16 * Michael Platings <mplatings@pixelpower.com>
17 */
18
19#ifndef OSGANIMATION_INTERPOLATOR
20#define OSGANIMATION_INTERPOLATOR 1
21
22#include <osg/Notify>
23#include <osgAnimation/Keyframe>
24
25namespace osgAnimation
26{
27
28 template <class TYPE, class KEY>
29 class TemplateInterpolatorBase
30 {
31 public:
32 typedef KEY KeyframeType;
33 typedef TYPE UsingType;
34
35 public:
36 TemplateInterpolatorBase() {}
37
38 int getKeyIndexFromTime(const TemplateKeyframeContainer<KEY>& keys, double time) const
39 {
40 int key_size = keys.size();
41 if (!key_size) {
42 osg::notify(osg::WARN) << "TemplateInterpolatorBase::getKeyIndexFromTime the container is empty, impossible to get key index from time" << std::endl;;
43 return -1;
44 }
45 const TemplateKeyframe<KeyframeType>* keysVector = &keys.front();
46 int k = 0;
47 int l = key_size;
48 int mid = key_size/2;
49 while(mid != k){
50 double time1 = keysVector[mid].getTime();
51 if(time1 < time){
52 k = mid;
53 } else {
54 l = mid;
55 }
56 mid = (l+k)/2;
57 }
58 return k;
59 }
60 };
61
62
63 template <class TYPE, class KEY=TYPE>
64 class TemplateStepInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
65 {
66 public:
67
68 TemplateStepInterpolator() {}
69 void getValue(const TemplateKeyframeContainer<KEY>& keyframes, double time, TYPE& result) const
70 {
71
72 if (time >= keyframes.back().getTime())
73 {
74 result = keyframes.back().getValue();
75 return;
76 }
77 else if (time <= keyframes.front().getTime())
78 {
79 result = keyframes.front().getValue();
80 return;
81 }
82
83 int i = this->getKeyIndexFromTime(keyframes,time);
84 result = keyframes[i].getValue();
85 }
86 };
87
88
89 template <class TYPE, class KEY=TYPE>
90 class TemplateLinearInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
91 {
92 public:
93
94 TemplateLinearInterpolator() {}
95 void getValue(const TemplateKeyframeContainer<KEY>& keyframes, double time, TYPE& result) const
96 {
97
98 if (time >= keyframes.back().getTime())
99 {
100 result = keyframes.back().getValue();
101 return;
102 }
103 else if (time <= keyframes.front().getTime())
104 {
105 result = keyframes.front().getValue();
106 return;
107 }
108
109 int i = this->getKeyIndexFromTime(keyframes,time);
110 float blend = (time - keyframes[i].getTime()) / ( keyframes[i+1].getTime() - keyframes[i].getTime());
111 const TYPE& v1 = keyframes[i].getValue();
112 const TYPE& v2 = keyframes[i+1].getValue();
113 result = v1*(1-blend) + v2*blend;
114 }
115 };
116
117
118 template <class TYPE, class KEY=TYPE>
119 class TemplateSphericalLinearInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
120 {
121 public:
122 TemplateSphericalLinearInterpolator() {}
123 void getValue(const TemplateKeyframeContainer<KEY>& keyframes, double time, TYPE& result) const
124 {
125 if (time >= keyframes.back().getTime())
126 {
127 result = keyframes.back().getValue();
128 return;
129 }
130 else if (time <= keyframes.front().getTime())
131 {
132 result = keyframes.front().getValue();
133 return;
134 }
135
136 int i = this->getKeyIndexFromTime(keyframes,time);
137 float blend = (time - keyframes[i].getTime()) / ( keyframes[i+1].getTime() - keyframes[i].getTime());
138 const TYPE& q1 = keyframes[i].getValue();
139 const TYPE& q2 = keyframes[i+1].getValue();
140 result.slerp(blend,q1,q2);
141 }
142 };
143
144
145 template <class TYPE, class KEY>
146 class TemplateLinearPackedInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
147 {
148 public:
149
150 TemplateLinearPackedInterpolator() {}
151 void getValue(const TemplateKeyframeContainer<KEY>& keyframes, double time, TYPE& result) const
152 {
153 if (time >= keyframes.back().getTime())
154 {
155 keyframes.back().getValue().uncompress(keyframes.mScale, keyframes.mMin, result);
156 return;
157 }
158 else if (time <= keyframes.front().getTime())
159 {
160 keyframes.front().getValue().uncompress(keyframes.mScale, keyframes.mMin, result);
161 return;
162 }
163
164 int i = this->getKeyIndexFromTime(keyframes,time);
165 float blend = (time - keyframes[i].getTime()) / ( keyframes[i+1].getTime() - keyframes[i].getTime());
166 TYPE v1,v2;
167 keyframes[i].getValue().uncompress(keyframes.mScale, keyframes.mMin, v1);
168 keyframes[i+1].getValue().uncompress(keyframes.mScale, keyframes.mMin, v2);
169 result = v1*(1-blend) + v2*blend;
170 }
171 };
172
173
174 // http://en.wikipedia.org/wiki/B%C3%A9zier_curve
175 template <class TYPE, class KEY=TYPE>
176 class TemplateCubicBezierInterpolator : public TemplateInterpolatorBase<TYPE,KEY>
177 {
178 public:
179
180 TemplateCubicBezierInterpolator() {}
181 void getValue(const TemplateKeyframeContainer<KEY>& keyframes, double time, TYPE& result) const
182 {
183
184 if (time >= keyframes.back().getTime())
185 {
186 result = keyframes.back().getValue().getPosition();
187 return;
188 }
189 else if (time <= keyframes.front().getTime())
190 {
191 result = keyframes.front().getValue().getPosition();
192 return;
193 }
194
195 int i = this->getKeyIndexFromTime(keyframes,time);
196
197 float t = (time - keyframes[i].getTime()) / ( keyframes[i+1].getTime() - keyframes[i].getTime());
198 float one_minus_t = 1.0-t;
199 float one_minus_t2 = one_minus_t * one_minus_t;
200 float one_minus_t3 = one_minus_t2 * one_minus_t;
201 float t2 = t * t;
202
203 TYPE v0 = keyframes[i].getValue().getPosition() * one_minus_t3;
204 TYPE v1 = keyframes[i].getValue().getControlPointIn() * (3.0 * t * one_minus_t2);
205 TYPE v2 = keyframes[i].getValue().getControlPointOut() * (3.0 * t2 * one_minus_t);
206 TYPE v3 = keyframes[i+1].getValue().getPosition() * (t2 * t);
207
208 result = v0 + v1 + v2 + v3;
209 }
210 };
211
212 typedef TemplateStepInterpolator<double, double> DoubleStepInterpolator;
213 typedef TemplateStepInterpolator<float, float> FloatStepInterpolator;
214 typedef TemplateStepInterpolator<osg::Vec2, osg::Vec2> Vec2StepInterpolator;
215 typedef TemplateStepInterpolator<osg::Vec3, osg::Vec3> Vec3StepInterpolator;
216 typedef TemplateStepInterpolator<osg::Vec3, Vec3Packed> Vec3PackedStepInterpolator;
217 typedef TemplateStepInterpolator<osg::Vec4, osg::Vec4> Vec4StepInterpolator;
218 typedef TemplateStepInterpolator<osg::Quat, osg::Quat> QuatStepInterpolator;
219
220 typedef TemplateLinearInterpolator<double, double> DoubleLinearInterpolator;
221 typedef TemplateLinearInterpolator<float, float> FloatLinearInterpolator;
222 typedef TemplateLinearInterpolator<osg::Vec2, osg::Vec2> Vec2LinearInterpolator;
223 typedef TemplateLinearInterpolator<osg::Vec3, osg::Vec3> Vec3LinearInterpolator;
224 typedef TemplateLinearInterpolator<osg::Vec3, Vec3Packed> Vec3PackedLinearInterpolator;
225 typedef TemplateLinearInterpolator<osg::Vec4, osg::Vec4> Vec4LinearInterpolator;
226 typedef TemplateSphericalLinearInterpolator<osg::Quat, osg::Quat> QuatSphericalLinearInterpolator;
227 typedef TemplateLinearInterpolator<osg::Matrixf, osg::Matrixf> MatrixLinearInterpolator;
228
229 typedef TemplateCubicBezierInterpolator<float, FloatCubicBezier > FloatCubicBezierInterpolator;
230 typedef TemplateCubicBezierInterpolator<double, DoubleCubicBezier> DoubleCubicBezierInterpolator;
231 typedef TemplateCubicBezierInterpolator<osg::Vec2, Vec2CubicBezier> Vec2CubicBezierInterpolator;
232 typedef TemplateCubicBezierInterpolator<osg::Vec3, Vec3CubicBezier> Vec3CubicBezierInterpolator;
233 typedef TemplateCubicBezierInterpolator<osg::Vec4, Vec4CubicBezier> Vec4CubicBezierInterpolator;
234
235}
236#endif