root/OpenSceneGraph/trunk/src/osgAnimation/Timeline.cpp @ 11009

Revision 11009, 7.4 kB (checked in by robert, 5 years ago)

From Cedric Pinson, "Here a list of changes:
Bone now inherit from MatrixTransform?. It simplify a lot the update of
Bone matrix. It helps to have the bone system more generic. eg it's now
possible to have animation data with precomputed bind matrix. The other
benefit, is now the collada plugin will be able to use osgAnimation to
display skinned mesh. Michael Plating did a great work to improve this
aspect, he is working on the collada plugin and should be able to submit
a new version soon.
The RigGeometry? has been refactored so now it works when you save and
reload RigGeometry? because the source is not touched anymore. The
benefit with this update is that it should be now possible to use a
MorphGeometry? as source for a RigGeometry?.

The bad news is that the format has changed, so i have rebuild osg-data
related to osgAnimation data, updated the blender exporter to export to
the new format.
The fbx plugin could be touched about this commit, i dont compile it so
i can't give more information about it.
The bvh plugin has been updated by Wang rui so this one is fixed with
the new code of osgAnimation.
The examples has been updated to work with the new code too...

The example osg-data/example.osg should be remove, it's an old example
that does not work.

For people using blender the blender exporter up to date is here:
http://hg.plopbyte.net/osgexport2/
it will be merge to http://hg.plopbyte.net/osgexport/ as soon as the
modification will be push in the trunk.
"

RevLine 
[9093]1/*  -*-c++-*-
[10561]2 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
[9093]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#include <osgAnimation/Timeline>
[10344]16#include <osgAnimation/StatsVisitor>
[9628]17#include <limits.h>
[9093]18
19using namespace osgAnimation;
20
[9150]21
[10904]22Timeline::Timeline()
[9150]23{
[9370]24    _lastUpdate = 0;
25    _currentFrame = 0;
26    _fps = 25;
27    _speed = 1.0;
28    _state = Stop;
29    _initFirstFrame = false;
30    _previousFrameEvaluated = 0;
31    _evaluating = 0;
[9628]32    _numberFrame = UINT_MAX; // something like infinity
[10344]33    _collectStats = false;
34    _stats = new osg::Stats("Timeline");
[9370]35    setName("Timeline");
[9093]36}
[9150]37
[10904]38Timeline::Timeline(const Timeline& nc,const osg::CopyOp& op)
[10386]39    : Action(nc, op),
40      _actions(nc._actions)
[9150]41{
[9370]42    _lastUpdate = 0;
43    _currentFrame = 0;
44    _fps = 25;
45    _speed = 1.0;
46    _state = Stop;
47    _initFirstFrame = false;
48    _previousFrameEvaluated = 0;
49    _evaluating = 0;
[9628]50    _numberFrame = UINT_MAX; // something like infinity
[10344]51    _collectStats = false;
52    _stats = new osg::Stats("Timeline");
[9370]53    setName("Timeline");
[9150]54}
[10344]55
[10878]56void Timeline::setAnimationManager(AnimationManagerBase* manager)
57{
58    _animationManager = manager;
59}
60
[10904]61void Timeline::traverse(ActionVisitor& visitor)
[10344]62{
[10561]63    int layer = visitor.getCurrentLayer();
[10344]64    visitor.pushTimelineOnStack(this);
65    // update from high priority to low priority
66    for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); iterAnim != _actions.rend(); ++iterAnim )
67    {
[10561]68        visitor.setCurrentLayer(iterAnim->first);
[10344]69        ActionList& list = iterAnim->second;
70        for (unsigned int i = 0; i < list.size(); i++)
71        {
72            visitor.pushFrameActionOnStack(list[i]);
73            if (list[i].second) list[i].second->accept(visitor);
74            visitor.popFrameAction();
75        }
76    }
77    visitor.popTimeline();
[10561]78    visitor.setCurrentLayer(layer);
[10344]79}
80
81
[10904]82void Timeline::setStats(osg::Stats* stats) { _stats = stats;}
83osg::Stats* Timeline::getStats() { return _stats.get();}
84void Timeline::collectStats(bool state) { _collectStats = state;}
85StatsActionVisitor* Timeline::getStatsVisitor() { return _statsVisitor.get(); }
[10344]86
[10904]87void Timeline::clearActions()
[10344]88{
89    _actions.clear();
90    _addActionOperations.clear();
91    _removeActionOperations.clear();
92}
93
[10904]94void Timeline::update(double simulationTime)
[10344]95{
96    // first time we call update we generate one frame
97    UpdateActionVisitor updateTimeline;
98    if (!_initFirstFrame)
99    {
100        _lastUpdate = simulationTime;
101        _initFirstFrame = true;
102
[10878]103
104        _animationManager->clearTargets();
[10344]105        updateTimeline.setFrame(_currentFrame);
106        accept(updateTimeline);
107
108        if (_collectStats)
109        {
110            if (!_statsVisitor)
[10904]111                _statsVisitor = new StatsActionVisitor();
[10351]112            _statsVisitor->setStats(_stats.get());
[10344]113            _statsVisitor->setFrame(_currentFrame);
114            _statsVisitor->reset();
115            accept(*_statsVisitor);
116        }
117
118        processPendingOperation();
119    }
120
121    // find the number of frame pass since the last update
122    double delta = (simulationTime - _lastUpdate);
123    double nbframes = delta * _fps * _speed;
124    unsigned int nb = static_cast<unsigned int>(floor(nbframes));
125
126    for (unsigned int i = 0; i < nb; i++)
127    {
128        if (_state == Play)
129            _currentFrame++;
130
[10878]131        _animationManager->clearTargets();
[10344]132        updateTimeline.setFrame(_currentFrame);
133        accept(updateTimeline);
134        if (_collectStats)
135        {
136            if (!_statsVisitor)
137                _statsVisitor = new StatsActionVisitor;
[10351]138            _statsVisitor->setStats(_stats.get());
[10344]139            _statsVisitor->setFrame(_currentFrame);
140            _statsVisitor->reset();
141            accept(*_statsVisitor);
142        }
143
144        processPendingOperation();
145    }
146    if (nb)
147    {
148        _lastUpdate += ((double)nb) / _fps;
149    }
150}
151
[10904]152void Timeline::removeAction(Action* action)
[10344]153{
154    if (getEvaluating())
155        _removeActionOperations.push_back(FrameAction(0, action));
156    else
157        internalRemoveAction(action);
158}
159
[10904]160void Timeline::addActionAt(unsigned int frame, Action* action, int priority)
[10344]161{
[10878]162    // skip if this action has already been added this frame
163    for (CommandList::iterator it = _addActionOperations.begin(); it != _addActionOperations.end(); ++it)
164    {
165        Command& command = *it;
166        if (command._action.second.get() == action) {
167            osg::notify(osg::INFO) << "Timeline::addActionAt command " << action->getName() << " already added this frame, declined" << std::endl;
168            return;
169        }
170    }
171
172    if (isActive(action))
173    {
174        osg::notify(osg::INFO) << "Timeline::addActionAt command " << action->getName() << " already active, remove the old" << std::endl;
175        removeAction(action);
176    }
177
[10344]178    if (getEvaluating())
179        _addActionOperations.push_back(Command(priority,FrameAction(frame, action)));
180    else
181        internalAddAction(priority, FrameAction(frame, action));
182}
[10904]183void Timeline::addActionAt(double t, Action* action, int priority)
[10344]184{
185    unsigned int frame = static_cast<unsigned int>(floor(t * _fps));
186    addActionAt(frame, action, priority);
187}
188
[10904]189void Timeline::addActionNow(Action* action, int priority)
[10344]190{
[10394]191    addActionAt(getCurrentFrame()+1, action, priority);
[10344]192}
193
[10904]194void Timeline::processPendingOperation()
[10344]195{
196    // process all pending add action operation
197    while( !_addActionOperations.empty())
198    {
199        internalAddAction(_addActionOperations.back()._priority, _addActionOperations.back()._action);
200        _addActionOperations.pop_back();
201    }
202
203    // process all pending remove action operation
204    while( !_removeActionOperations.empty())
205    {
206        internalRemoveAction(_removeActionOperations.back().second.get());
207        _removeActionOperations.pop_back();
208    }
209}
210
[10904]211void Timeline::internalRemoveAction(Action* action)
[10344]212{
[11009]213    for (ActionLayers::iterator it = _actions.begin(); it != _actions.end(); ++it)
[10344]214    {
215        ActionList& fa = it->second;
216        for (unsigned int i = 0; i < fa.size(); i++)
217            if (fa[i].second.get() == action)
218            {
219                fa.erase(fa.begin() + i);
220                return;
221            }
222    }
223}
224
[10904]225void Timeline::internalAddAction(int priority, const FrameAction& ftl)
[10344]226{
227    _actions[priority].insert(_actions[priority].begin(), ftl);
228}
229
[10904]230bool Timeline::isActive(Action* activeAction)
[10344]231{
232    // update from high priority to low priority
233    for( ActionLayers::iterator iterAnim = _actions.begin(); iterAnim != _actions.end(); ++iterAnim )
234    {
235        // update all animation
236        ActionList& list = iterAnim->second;
237        for (unsigned int i = 0; i < list.size(); i++)
238        {
239            Action* action = list[i].second.get();
240            if (action == activeAction)
241            {
242                unsigned int firstFrame = list[i].first;
243                // check if current frame of timeline hit an action interval
244                if (_currentFrame >= firstFrame &&
245                    _currentFrame < (firstFrame + action->getNumFrames()) )
246                    return true;
247            }
248        }
249    }
250    return false;
251}
Note: See TracBrowser for help on using the browser.