root/OpenSceneGraph/trunk/src/osg/AnimationPath.cpp @ 13041

Revision 13041, 8.6 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13#include <osg/AnimationPath>
14#include <osg/MatrixTransform>
15#include <osg/PositionAttitudeTransform>
16#include <osg/Camera>
17#include <osg/CameraView>
18#include <osg/io_utils>
19
20using namespace osg;
21
22void AnimationPath::insert(double time,const ControlPoint& controlPoint)
23{
24    _timeControlPointMap[time] = controlPoint;
25}
26
27bool AnimationPath::getInterpolatedControlPoint(double time,ControlPoint& controlPoint) const
28{
29    if (_timeControlPointMap.empty()) return false;
30
31    switch(_loopMode)
32    {
33        case(SWING):
34        {
35            double modulated_time = (time - getFirstTime())/(getPeriod()*2.0);
36            double fraction_part = modulated_time - floor(modulated_time);
37            if (fraction_part>0.5) fraction_part = 1.0-fraction_part;
38
39            time = getFirstTime()+(fraction_part*2.0) * getPeriod();
40            break;
41        }
42        case(LOOP):
43        {
44            double modulated_time = (time - getFirstTime())/getPeriod();
45            double fraction_part = modulated_time - floor(modulated_time);
46            time = getFirstTime()+fraction_part * getPeriod();
47            break;
48        }
49        case(NO_LOOPING):
50            // no need to modulate the time.
51            break;
52    }
53
54
55
56    TimeControlPointMap::const_iterator second = _timeControlPointMap.lower_bound(time);
57    if (second==_timeControlPointMap.begin())
58    {
59        controlPoint = second->second;
60    }
61    else if (second!=_timeControlPointMap.end())
62    {
63        TimeControlPointMap::const_iterator first = second;
64        --first;
65
66        // we have both a lower bound and the next item.
67
68        // delta_time = second.time - first.time
69        double delta_time = second->first - first->first;
70
71        if (delta_time==0.0)
72            controlPoint = first->second;
73        else
74        {
75            controlPoint.interpolate((time - first->first)/delta_time,
76                            first->second,
77                            second->second);
78        }
79    }
80    else // (second==_timeControlPointMap.end())
81    {
82        controlPoint = _timeControlPointMap.rbegin()->second;
83    }
84    return true;
85}
86
87
88void AnimationPath::read(std::istream& in)
89{
90    while (!in.eof())
91    {
92        double time;
93        osg::Vec3d position;
94        osg::Quat rotation;
95        in >> time >> position.x() >> position.y() >> position.z() >> rotation.x() >> rotation.y() >> rotation.z() >> rotation.w();
96        if(!in.eof())
97            insert(time,osg::AnimationPath::ControlPoint(position,rotation));
98    }
99}
100
101void AnimationPath::write(TimeControlPointMap::const_iterator itr, std::ostream& fout) const
102{
103    const ControlPoint& cp = itr->second;
104    fout<<itr->first<<" "<<cp.getPosition()<<" "<<cp.getRotation()<<std::endl;
105}
106
107void AnimationPath::write(std::ostream& fout) const
108{
109    int prec = fout.precision();
110    fout.precision(15);
111
112    const TimeControlPointMap& tcpm = getTimeControlPointMap();
113    for(TimeControlPointMap::const_iterator tcpmitr=tcpm.begin();
114        tcpmitr!=tcpm.end();
115        ++tcpmitr)
116    {
117        write(tcpmitr, fout);
118    }
119
120    fout.precision(prec);
121}
122
123AnimationPathCallback::AnimationPathCallback(const osg::Vec3d& pivot,const osg::Vec3d& axis,float angularVelocity):
124            _pivotPoint(pivot),
125            _useInverseMatrix(false),
126            _timeOffset(0.0),
127            _timeMultiplier(1.0),
128            _firstTime(DBL_MAX),
129            _latestTime(0.0),
130            _pause(false),
131            _pauseTime(0.0)
132{
133    _animationPath = new AnimationPath;
134    _animationPath->setLoopMode(osg::AnimationPath::LOOP);
135
136    double time0 = 0.0;
137    double time1 = osg::PI*0.5/angularVelocity;
138    double time2 = osg::PI*1.0/angularVelocity;
139    double time3 = osg::PI*1.5/angularVelocity;
140    double time4 = osg::PI*2.0/angularVelocity;
141
142    osg::Quat rotation0(0.0, axis);
143    osg::Quat rotation1(osg::PI*0.5, axis);
144    osg::Quat rotation2(osg::PI*1.0, axis);
145    osg::Quat rotation3(osg::PI*1.5, axis);
146
147
148    _animationPath->insert(time0,osg::AnimationPath::ControlPoint(pivot,rotation0));
149    _animationPath->insert(time1,osg::AnimationPath::ControlPoint(pivot,rotation1));
150    _animationPath->insert(time2,osg::AnimationPath::ControlPoint(pivot,rotation2));
151    _animationPath->insert(time3,osg::AnimationPath::ControlPoint(pivot,rotation3));
152    _animationPath->insert(time4,osg::AnimationPath::ControlPoint(pivot,rotation0));
153}
154
155class AnimationPathCallbackVisitor : public NodeVisitor
156{
157    public:
158
159        AnimationPathCallbackVisitor(const AnimationPath::ControlPoint& cp, const osg::Vec3d& pivotPoint, bool useInverseMatrix):
160            _cp(cp),
161            _pivotPoint(pivotPoint),
162            _useInverseMatrix(useInverseMatrix) {}
163
164        virtual void apply(Camera& camera)
165        {
166            Matrix matrix;
167            if (_useInverseMatrix)
168                _cp.getInverse(matrix);
169            else
170                _cp.getMatrix(matrix);
171
172            camera.setViewMatrix(osg::Matrix::translate(-_pivotPoint)*matrix);
173        }
174
175
176        virtual void apply(CameraView& cv)
177        {
178            if (_useInverseMatrix)
179            {
180                Matrix matrix;
181                _cp.getInverse(matrix);
182                cv.setPosition(matrix.getTrans());
183                cv.setAttitude(_cp.getRotation().inverse());
184                cv.setFocalLength(1.0f/_cp.getScale().x());
185
186            }
187            else
188            {
189                cv.setPosition(_cp.getPosition());
190                cv.setAttitude(_cp.getRotation());
191                cv.setFocalLength(_cp.getScale().x());
192            }
193        }
194
195        virtual void apply(MatrixTransform& mt)
196        {
197            Matrix matrix;
198            if (_useInverseMatrix)
199                _cp.getInverse(matrix);
200            else
201                _cp.getMatrix(matrix);
202
203            mt.setMatrix(osg::Matrix::translate(-_pivotPoint)*matrix);
204        }
205
206        virtual void apply(PositionAttitudeTransform& pat)
207        {
208            if (_useInverseMatrix)
209            {
210                Matrix matrix;
211                _cp.getInverse(matrix);
212                pat.setPosition(matrix.getTrans());
213                pat.setAttitude(_cp.getRotation().inverse());
214                pat.setScale(osg::Vec3(1.0f/_cp.getScale().x(),1.0f/_cp.getScale().y(),1.0f/_cp.getScale().z()));
215                pat.setPivotPoint(_pivotPoint);
216
217            }
218            else
219            {
220                pat.setPosition(_cp.getPosition());
221                pat.setAttitude(_cp.getRotation());
222                pat.setScale(_cp.getScale());
223                pat.setPivotPoint(_pivotPoint);
224            }
225        }
226
227        AnimationPath::ControlPoint _cp;
228        osg::Vec3d _pivotPoint;
229        bool _useInverseMatrix;
230};
231
232void AnimationPathCallback::operator()(Node* node, NodeVisitor* nv)
233{
234    if (_animationPath.valid() &&
235        nv->getVisitorType()==NodeVisitor::UPDATE_VISITOR &&
236        nv->getFrameStamp())
237    {
238        double time = nv->getFrameStamp()->getSimulationTime();
239        _latestTime = time;
240
241        if (!_pause)
242        {
243            // Only update _firstTime the first time, when its value is still DBL_MAX
244            if (_firstTime==DBL_MAX) _firstTime = time;
245            update(*node);
246        }
247    }
248
249    // must call any nested node callbacks and continue subgraph traversal.
250    NodeCallback::traverse(node,nv);
251}
252
253double AnimationPathCallback::getAnimationTime() const
254{
255    return ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier;
256}
257
258void AnimationPathCallback::update(osg::Node& node)
259{
260    AnimationPath::ControlPoint cp;
261    if (_animationPath->getInterpolatedControlPoint(getAnimationTime(),cp))
262    {
263        AnimationPathCallbackVisitor apcv(cp,_pivotPoint,_useInverseMatrix);
264        node.accept(apcv);
265    }
266}
267
268
269void AnimationPathCallback::reset()
270{
271#if 1
272    _firstTime = DBL_MAX;
273    _pauseTime = DBL_MAX;
274#else
275    _firstTime = _latestTime;
276    _pauseTime = _latestTime;
277#endif
278}
279
280void AnimationPathCallback::setPause(bool pause)
281{
282    if (_pause==pause)
283    {
284        return;
285    }
286
287    _pause = pause;
288
289    if (_firstTime==DBL_MAX) return;
290
291    if (_pause)
292    {
293        _pauseTime = _latestTime;
294    }
295    else
296    {
297        _firstTime += (_latestTime-_pauseTime);
298    }
299}
Note: See TracBrowser for help on using the browser.