openscenegraph
Target
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
15
16#ifndef OSGANIMATION_TARGET
17#define OSGANIMATION_TARGET 1
18
19#include <vector>
20#include <osg/Quat>
21#include <osg/Vec3>
22#include <osg/Vec2>
23#include <osg/Vec4>
24#include <osg/Referenced>
25#include <osgAnimation/Export>
26
27namespace osgAnimation
28{
29
30 class Channel;
31
32 class OSGANIMATION_EXPORT Target : public osg::Referenced
33 {
34 public:
35
36 Target();
37 virtual ~Target() {}
38 void reset() { _weight = 0; _priorityWeight = 0; }
39 int getCount() const { return referenceCount(); }
40 float getWeight() const { return _weight; }
41 protected:
42 float _weight;
43 float _priorityWeight;
44 int _lastPriority;
45 };
46
47
48 template <class T>
49 class TemplateTarget : public Target
50 {
51 public:
52
53 TemplateTarget() : _target() {}
54 TemplateTarget(const T& v) { setValue(v); }
55 TemplateTarget(const TemplateTarget& v) { setValue(v.getValue()); }
56
57 inline void lerp(float t, const T& a, const T& b);
58
59 /**
60 * The priority is used to detect a change of priority
61 * It's important to update animation target in priority
62 * order. eg:
63 * all animation with priority 1
64 * all animation with priority 0
65 * all animation with priority -1
66 * ...
67 */
68 void update(float weight, const T& val, int priority)
69 {
70 if (_weight || _priorityWeight)
71 {
72 if (_lastPriority != priority)
73 {
74 // change in priority
75 // add to weight with the same previous priority cumulated weight
76 _weight += _priorityWeight * (1.0 - _weight);
77 _priorityWeight = 0;
78 _lastPriority = priority;
79 }
80
81 _priorityWeight += weight;
82 float t = (1.0 - _weight) * weight / _priorityWeight;
83 lerp(t, _target, val);
84 }
85 else
86 {
87 _priorityWeight = weight;
88 _lastPriority = priority;
89 _target = val;
90 }
91 }
92 const T& getValue() const { return _target; }
93
94 void setValue(const T& value) { _target = value; }
95
96 protected:
97
98 T _target;
99 };
100
101 template <class T>
102 inline void TemplateTarget<T>::lerp(float t, const T& a, const T& b)
103 {
104 _target = a * (1.0f - t) + b * t;
105 }
106
107 template <>
108 inline void TemplateTarget<osg::Quat>::lerp(float t, const osg::Quat& a, const osg::Quat& b)
109 {
110 if (a.asVec4() * b.asVec4() < 0.0)
111 {
112 _target = a * (1.0f - t) + b * -t;
113 }
114 else
115 {
116 _target = a * (1.0f - t) + b * t;
117 }
118
119 osg::Quat::value_type len2 = _target.length2();
120 if ( len2 != 1.0 && len2 != 0.0)
121 _target *= 1.0/sqrt(len2);
122 }
123
124 typedef TemplateTarget<osg::Matrixf> MatrixTarget;
125 typedef TemplateTarget<osg::Quat> QuatTarget;
126 typedef TemplateTarget<osg::Vec3> Vec3Target;
127 typedef TemplateTarget<osg::Vec4> Vec4Target;
128 typedef TemplateTarget<osg::Vec2> Vec2Target;
129 typedef TemplateTarget<float> FloatTarget;
130 typedef TemplateTarget<double> DoubleTarget;
131
132}
133
134#endif