#
root/OpenSceneGraph/trunk/include/osgAnimation/EaseMotion
@
9981

Revision 9981, 10.9 kB (checked in by cedricpinson, 7 years ago) |
---|

Rev | Line | |
---|---|---|

[9093] | 1 | /* -*-c++-*- |

2 | * Copyright (C) 2008 Cedric Pinson <mornifle@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 | ||

15 | #ifndef OSGANIMATION_EASE_MOTION_H | |

16 | #define OSGANIMATION_EASE_MOTION_H | |

17 | ||

[9370] | 18 | #include <osg/Referenced> |

19 | #include <osg/ref_ptr> | |

20 | #include <osg/Notify> | |

21 | #include <osg/Math> | |

22 | #include <vector> | |

23 | ||

[9093] | 24 | namespace osgAnimation { |

25 | ||

26 | ||

27 | struct OutBounceFunction | |

28 | { | |

29 | inline static void getValueAt(float t, float& result) | |

30 | { | |

31 | if ((t) < (1/2.75)) | |

32 | { | |

33 | result = 7.5625 * t * t; | |

34 | } | |

35 | else if (t < (2/2.75)) | |

36 | { | |

37 | t = t - (1.5/2.75); | |

38 | result = 7.5625* t * t + .75; | |

39 | } | |

40 | else if (t < (2.5/2.75)) | |

41 | { | |

42 | t = t - (2.25/2.75); | |

43 | result = 7.5625 * t * t + .9375; | |

44 | } | |

45 | else | |

46 | { | |

47 | t = t - (2.625/2.75); | |

48 | result = 7.5625* t * t + .984375; | |

49 | } | |

50 | } | |

51 | }; | |

52 | ||

53 | struct InBounceFunction | |

54 | { | |

55 | inline static void getValueAt(float t, float& result) | |

56 | { | |

57 | OutBounceFunction::getValueAt(1-t, result); | |

58 | result = 1 - result; | |

59 | } | |

60 | }; | |

61 | ||

62 | struct InOutBounceFunction | |

63 | { | |

64 | inline static void getValueAt(float t, float& result) | |

65 | { | |

66 | if (t < 0.5) | |

67 | { | |

68 | InBounceFunction::getValueAt(t * 2, result); | |

69 | result *= 0.5; | |

70 | } | |

71 | else | |

72 | { | |

73 | OutBounceFunction::getValueAt(t * 2 - 1 , result); | |

74 | result = result * 0.5 + 0.5; | |

75 | } | |

76 | } | |

77 | }; | |

78 | ||

[9286] | 79 | |

80 | /// Linear function | |

81 | struct LinearFunction | |

82 | { | |

83 | inline static void getValueAt(float t, float& result) { result = t;} | |

84 | }; | |

85 | ||

[9093] | 86 | |

[9286] | 87 | /// Quad function |

[9093] | 88 | struct OutQuadFunction |

89 | { | |

90 | inline static void getValueAt(float t, float& result) { result = - (t * (t -2.0));} | |

91 | }; | |

92 | ||

93 | struct InQuadFunction | |

94 | { | |

95 | inline static void getValueAt(float t, float& result) { result = t*t;} | |

96 | }; | |

97 | struct InOutQuadFunction | |

98 | { | |

99 | inline static void getValueAt(float t, float& result) | |

100 | { | |

101 | t = t * 2.0; | |

102 | if (t < 1.0) | |

103 | result = 0.5 * t * t; | |

104 | else | |

105 | { | |

106 | t = t - 1.0; | |

107 | result = - 0.5 * t * ( t - 2) - 1; | |

108 | } | |

109 | } | |

110 | }; | |

111 | ||

112 | ||

[9286] | 113 | /// Cubic function |

[9093] | 114 | struct OutCubicFunction |

115 | { | |

116 | inline static void getValueAt(float t, float& result) { t = t-1.0; result = t*t*t + 1;} | |

117 | }; | |

118 | struct InCubicFunction | |

119 | { | |

120 | inline static void getValueAt(float t, float& result) { result = t*t*t;} | |

121 | }; | |

122 | struct InOutCubicFunction | |

123 | { | |

124 | inline static void getValueAt(float t, float& result) | |

125 | { | |

126 | t = t * 2; | |

127 | if (t < 1.0) | |

128 | result = 0.5 * t * t * t; | |

129 | else { | |

130 | t = t - 2; | |

131 | result = 0.5 * t * t * t + 2; | |

132 | } | |

133 | } | |

134 | }; | |

135 | ||

[9286] | 136 | |

137 | /// Quart function | |

138 | struct InQuartFunction | |

139 | { | |

140 | inline static void getValueAt(float t, float& result) { result = t*t*t*t*t;} | |

141 | }; | |

142 | ||

143 | struct OutQuartFunction | |

144 | { | |

145 | inline static void getValueAt(float t, float& result) { t = t - 1; result = - (t*t*t*t -1); } | |

146 | }; | |

147 | ||

148 | struct InOutQuartFunction | |

149 | { | |

150 | inline static void getValueAt(float t, float& result) | |

151 | { | |

152 | t = t * 2.0; | |

153 | if ( t < 1) | |

154 | result = 0.5*t*t*t*t; | |

155 | else | |

156 | { | |

157 | t -= 2.0; | |

158 | result = -0.5 * (t*t*t*t -2); | |

159 | } | |

160 | } | |

161 | }; | |

162 | ||

[9981] | 163 | /// Elastic function |

164 | struct OutElasticFunction | |

165 | { | |

166 | inline static void getValueAt(float t, float& result) | |

167 | { | |

168 | result = pow(2.0f, -10.0f * t) * sinf((t - 0.3f / 4.0f) * (2.0f * osg::PI) / 0.3f) + 1.0f; | |

169 | } | |

170 | }; | |

[9286] | 171 | |

[9981] | 172 | struct InElasticFunction |

173 | { | |

174 | inline static void getValueAt(float t, float& result) | |

175 | { | |

176 | OutElasticFunction::getValueAt(1.0f - t, result); | |

177 | result = 1.0f - result; | |

178 | } | |

179 | }; | |

[9286] | 180 | |

[9981] | 181 | struct InOutElasticFunction |

182 | { | |

183 | inline static void getValueAt(float t, float& result) | |

184 | { | |

185 | t *= 2.0f; | |

186 | if (t < 1.0f) | |

187 | { | |

188 | t -= 1.0f; | |

189 | result = -0.5 * (1.0f * pow(2.0f, 10.0f * t) * sinf((t - 0.45f / 4.0f) * (2.0f * osg::PI) / 0.45f)); | |

190 | } | |

191 | else | |

192 | { | |

193 | t -= 1.0f; | |

194 | result = pow(2.0f, -10.0f * t) * sinf((t - 0.45f / 4.0f) * (2.0f * osg::PI) / 0.45f) * 0.5f + 1.0f; | |

195 | } | |

196 | } | |

197 | }; | |

198 | ||

199 | ||

[9370] | 200 | class Motion : public osg::Referenced |

[9093] | 201 | { |

202 | public: | |

203 | typedef float value_type; | |

204 | enum TimeBehaviour | |

205 | { | |

206 | CLAMP, | |

[9388] | 207 | LOOP |

[9093] | 208 | }; |

[9370] | 209 | Motion(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : _time(0), _startValue(startValue), _changeValue(changeValue), _duration(duration), _behaviour(tb) {} |

[9093] | 210 | virtual ~Motion() {} |

211 | void reset() { setTime(0);} | |

212 | float getTime() const { return _time; } | |

[9370] | 213 | float evaluateTime(float time) const |

[9093] | 214 | { |

215 | switch (_behaviour) | |

216 | { | |

217 | case CLAMP: | |

[9370] | 218 | if (time > _duration) |

219 | time = _duration; | |

220 | else if (time < 0.0) | |

221 | time = 0.0; | |

[9093] | 222 | break; |

223 | case LOOP: | |

[9370] | 224 | if (time <= 0) |

225 | time = 0; | |

226 | else | |

227 | time = fmodf(time, _duration); | |

[9093] | 228 | break; |

229 | } | |

[9370] | 230 | return time; |

[9093] | 231 | } |

[9370] | 232 | |

233 | void update(float dt) | |

234 | { | |

235 | _time = evaluateTime(_time + dt); | |

236 | } | |

[9093] | 237 | |

[9370] | 238 | void setTime(float time) { _time = evaluateTime(time);} |

[9093] | 239 | void getValue(value_type& result) const { getValueAt(_time, result); } |

240 | value_type getValue() const | |

241 | { | |

242 | value_type result; | |

243 | getValueAt(_time, result); | |

244 | return result; | |

245 | } | |

246 | ||

247 | void getValueAt(float time, value_type& result) const | |

248 | { | |

[9370] | 249 | getValueInNormalizedRange(evaluateTime(time)/_duration, result); |

250 | result = result * _changeValue + _startValue; | |

[9093] | 251 | } |

252 | value_type getValueAt(float time) const | |

253 | { | |

254 | value_type result; | |

[9370] | 255 | getValueAt(evaluateTime(time), result); |

[9093] | 256 | return result; |

257 | } | |

258 | ||

259 | virtual void getValueInNormalizedRange(float t, value_type& result) const = 0; | |

260 | ||

[9370] | 261 | float getDuration() const { return _duration;} |

[9093] | 262 | protected: |

263 | float _time; | |

[9370] | 264 | float _startValue; |

265 | float _changeValue; | |

266 | float _duration; | |

[9093] | 267 | TimeBehaviour _behaviour; |

268 | }; | |

269 | ||

270 | ||

[9286] | 271 | |

[9093] | 272 | template <typename T> |

273 | struct MathMotionTemplate : public Motion | |

274 | { | |

275 | MathMotionTemplate(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : Motion(startValue, duration, changeValue, tb) {} | |

276 | virtual void getValueInNormalizedRange(float t, value_type& result) const { T::getValueAt(t, result); } | |

277 | }; | |

278 | ||

279 | template <class T> | |

280 | struct SamplerMotionTemplate : public Motion | |

281 | { | |

282 | T _sampler; | |

283 | SamplerMotionTemplate(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : Motion(startValue, duration, changeValue, tb) {} | |

284 | T& getSampler() { return _sampler;} | |

285 | const T& getSampler() const { return _sampler;} | |

286 | virtual void getValueInNormalizedRange(float t, value_type& result) const | |

287 | { | |

288 | if (!_sampler.getKeyframeContainer()) | |

289 | { | |

290 | result = 0; | |

291 | return; | |

292 | } | |

293 | float size = _sampler.getEndTime() - _sampler.getStartTime(); | |

294 | t = t * size + _sampler.getStartTime(); | |

295 | _sampler.getValueAt(t, result); | |

296 | } | |

297 | }; | |

298 | ||

[9370] | 299 | struct CompositeMotion : public Motion |

300 | { | |

301 | typedef std::vector<osg::ref_ptr<Motion> > MotionList; | |

302 | MotionList _motions; | |

303 | ||

304 | MotionList& getMotionList() { return _motions; } | |

305 | const MotionList& getMotionList() const { return _motions; } | |

306 | CompositeMotion(float startValue = 0, float duration = 1, float changeValue = 1, TimeBehaviour tb = CLAMP) : Motion(startValue, duration, changeValue, tb) {} | |

[9093] | 307 | |

[9370] | 308 | virtual void getValueInNormalizedRange(float t, value_type& result) const |

309 | { | |

310 | if (_motions.empty()) | |

311 | { | |

312 | result = 0; | |

313 | osg::notify(osg::WARN) << "CompositeMotion::getValueInNormalizedRange no Motion in the CompositeMotion, add motion to have result" << std::endl; | |

314 | return; | |

315 | } | |

316 | for (MotionList::const_iterator it = _motions.begin(); it != _motions.end(); it++) | |

317 | { | |

318 | const Motion* motion = static_cast<const Motion*>(it->get()); | |

319 | float durationInRange = motion->getDuration() / getDuration(); | |

320 | if (t < durationInRange) | |

321 | { | |

322 | float tInRange = t/durationInRange * motion->getDuration(); | |

323 | motion->getValueAt( tInRange, result); | |

324 | return; | |

325 | } else | |

326 | t = t - durationInRange; | |

327 | } | |

328 | osg::notify(osg::WARN) << "CompositeMotion::getValueInNormalizedRange did find the value in range, something wrong" << std::endl; | |

329 | result = 0; | |

330 | } | |

331 | }; | |

[9093] | 332 | |

[9370] | 333 | |

[9093] | 334 | // linear |

335 | typedef MathMotionTemplate<LinearFunction > LinearMotion; | |

336 | ||

[9286] | 337 | // quad |

338 | typedef MathMotionTemplate<OutQuadFunction > OutQuadMotion; | |

339 | typedef MathMotionTemplate<InQuadFunction> InQuadMotion; | |

340 | typedef MathMotionTemplate<InOutQuadFunction> InOutQuadMotion; | |

341 | ||

[9093] | 342 | // cubic |

343 | typedef MathMotionTemplate<OutCubicFunction > OutCubicMotion; | |

344 | typedef MathMotionTemplate<InCubicFunction> InCubicMotion; | |

345 | typedef MathMotionTemplate<InOutCubicFunction> InOutCubicMotion; | |

346 | ||

[9286] | 347 | // quart |

348 | typedef MathMotionTemplate<OutQuartFunction > OutQuartMotion; | |

349 | typedef MathMotionTemplate<InQuartFunction> InQuartMotion; | |

350 | typedef MathMotionTemplate<InOutQuartFunction> InOutQuartMotion; | |

[9093] | 351 | |

[9286] | 352 | |

[9093] | 353 | // bounce |

354 | typedef MathMotionTemplate<OutBounceFunction > OutBounceMotion; | |

355 | typedef MathMotionTemplate<InBounceFunction> InBounceMotion; | |

356 | typedef MathMotionTemplate<InOutBounceFunction> InOutBounceMotion; | |

357 | ||

[9981] | 358 | // elastic |

359 | typedef MathMotionTemplate<OutElasticFunction > OutElasticMotion; | |

360 | typedef MathMotionTemplate<InElasticFunction > InElasticMotion; | |

361 | typedef MathMotionTemplate<InOutElasticFunction > InOutElasticMotion; | |

[9093] | 362 | |

363 | } | |

364 | ||

365 | #endif |

**Note:**See TracBrowser for help on using the browser.