root/OpenSceneGraph/trunk/examples/osganimationtimeline/osganimationtimeline.cpp @ 10697

Revision 10697, 8.0 kB (checked in by robert, 5 years ago)

From Cedric Pinson, updates to osganimation example to keep in sync with changes with osgAnimation, and introduction of a hardware skinning example

RevLine 
[9150]1/*  -*-c++-*-
[10487]2 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
[9150]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 <iostream>
16#include <osgDB/ReadFile>
17#include <osgViewer/ViewerEventHandlers>
18#include <osgGA/TrackballManipulator>
19#include <osgGA/FlightManipulator>
20#include <osgGA/DriveManipulator>
21#include <osgGA/KeySwitchMatrixManipulator>
22#include <osgGA/StateSetManipulator>
23#include <osgGA/AnimationPathManipulator>
24#include <osgGA/TerrainManipulator>
25
26#include <osgAnimation/Bone>
27#include <osgAnimation/Skeleton>
28#include <osgAnimation/RigGeometry>
29#include <osgAnimation/Timeline>
30#include <osgAnimation/AnimationManagerBase>
[9370]31#include <osgAnimation/TimelineAnimationManager>
[9150]32
[10697]33#include <osgAnimation/ActionStripAnimation>
34#include <osgAnimation/ActionBlendIn>
35#include <osgAnimation/ActionBlendOut>
36#include <osgAnimation/ActionAnimation>
[9150]37
[10697]38
[9150]39struct NoseBegin : public osgAnimation::Action::Callback
40{
[10625]41    virtual void operator()(osgAnimation::Action* action, osgAnimation::ActionVisitor* nv)
[9150]42    {
43        std::cout << "sacrebleu, it scratches my nose, let me scratch it" << std::endl;
44        std::cout << "process NoseBegin call back " << action->getName() << std::endl << std::endl;
45    }
46};
47
48struct NoseEnd : public osgAnimation::Action::Callback
49{
[10625]50    virtual void operator()(osgAnimation::Action* action, osgAnimation::ActionVisitor* nv)
[9150]51    {
52        std::cout << "shhhrt shrrrrt shhhhhhrrrrt, haaa it's better"<< std::endl;
53        std::cout << "process NoseEnd call back " << action->getName() << std::endl << std::endl;
54    }
55};
56
57struct ExampleTimelineUsage : public osgGA::GUIEventHandler
58{
[10697]59    osg::ref_ptr<osgAnimation::ActionStripAnimation> _mainLoop;
60    osg::ref_ptr<osgAnimation::ActionStripAnimation> _scratchHead;
61    osg::ref_ptr<osgAnimation::ActionStripAnimation> _scratchNose;
[9370]62    osg::ref_ptr<osgAnimation::TimelineAnimationManager> _manager;
[9150]63
64    bool _releaseKey;
65
[9370]66    ExampleTimelineUsage(osgAnimation::TimelineAnimationManager* manager)
[9150]67    {
68        _releaseKey = false;
69        _manager = manager;
70
[9370]71        const osgAnimation::AnimationList& list = _manager->getAnimationList();
72        osgAnimation::AnimationMap map;
73        for (osgAnimation::AnimationList::const_iterator it = list.begin(); it != list.end(); it++)
74            map[(*it)->getName()] = *it;
75
[10697]76        _mainLoop = new osgAnimation::ActionStripAnimation(map["Idle_Main"].get(),0.0,0.0);
[9150]77        _mainLoop->setLoop(0); // means forever
78
[10697]79        _scratchHead = new osgAnimation::ActionStripAnimation(map["Idle_Head_Scratch.02"].get(),0.2,0.3);
[9150]80        _scratchHead->setLoop(1); // one time
81
[9151]82        map["Idle_Nose_Scratch.01"]->setDuration(10.0); // set this animation duration to 10 seconds
[10697]83        _scratchNose = new osgAnimation::ActionStripAnimation(map["Idle_Nose_Scratch.01"].get(),0.2,0.3);
[9151]84        _scratchNose->setLoop(1); // one time
[9150]85
86        // add the main loop at priority 0 at time 0.
87       
88        osgAnimation::Timeline* tml = _manager->getTimeline();
89        tml->play();
90        tml->addActionAt(0.0, _mainLoop.get(), 0);
91
92
93        // add a scratch head priority 1 at 3.0 second.
94        tml->addActionAt(5.0, _scratchHead.get(), 1);
95
96        // populate time with scratch head
97        for (int i = 1; i < 20; i++)
98        {
99            // we add a scratch head priority 1 each 10 second
100            // note:
101            //      it's possible to add the same instance more then once on the timeline
102            //      the only things you need to take care is if you remove it. It will remove
103            //      all instance that exist on the timeline. If you need to differtiate
104            //      it's better to create a new instance
105            tml->addActionAt(5.0 + 10.0 * i, _scratchHead.get(), 1);
106        }
107
108        // we will add the scratch nose action only when the player hit a key
109        // in the operator()
110
111        // now we will add callback at end and begin of animation of Idle_Nose_Scratch.02
112        _scratchNose->setCallback(0.0, new NoseBegin);
113        _scratchNose->setCallback(_scratchNose->getNumFrames()-1, new NoseEnd);
114    }
115
[9459]116    bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&)
[9150]117    {
118        if (ea.getEventType() == osgGA::GUIEventAdapter::KEYUP)
119        {
120            _releaseKey = true;
121        }
122        return false;
123    }
124
125    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
126    {
127        if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
128        {
129            if (_releaseKey) // we hit a key and release it execute an action
130            {
131                osgAnimation::Timeline* tml = _manager->getTimeline();
132                // dont play if already playing
133                if (!tml->isActive(_scratchNose.get()))
134                {
135                    // add this animation on top of two other
136                    // we add one to evaluate the animation at the next frame, else we
137                    // will miss the current frame
138                    tml->addActionAt(tml->getCurrentFrame() + 1, _scratchNose.get(), 2);
139                }
140                _releaseKey = false;
141            }
142        }
143        else
144        {
145            osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv);
146            if (ev && ev->getActionAdapter() && !ev->getEvents().empty())
147            {
148                for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
149                    itr != ev->getEvents().end();
150                    ++itr)
151                {
152                    handleWithCheckAgainstIgnoreHandledEventsMask(*(*itr), *(ev->getActionAdapter()), node, nv);
153                }
154            }
155        }           
156        traverse(node, nv);
157    }
158
159};
160
161
162int main (int argc, char* argv[])
163{
[10487]164    std::cerr << "This example works only with nathan.osg" << std::endl;
[9150]165
166    osg::ArgumentParser psr(&argc, argv);
167
168    osgViewer::Viewer viewer(psr);
169
[10487]170    std::string file = "nathan.osg";
[9150]171    if(argc >= 2)
172        file = psr[1];
173
174    // replace the manager
[9370]175    osg::Group* root = dynamic_cast<osg::Group*>(osgDB::readNodeFile(file));
[10487]176    if (!root) {
177        osg::notify(osg::FATAL) << "can't read file " << file << std::endl;
178        return 1;
179    }
[9370]180    osgAnimation::AnimationManagerBase* animationManager = dynamic_cast<osgAnimation::AnimationManagerBase*>(root->getUpdateCallback());
[9150]181    if(!animationManager)
182    {
[10487]183        osg::notify(osg::FATAL) << "Did not find AnimationManagerBase updateCallback needed to animate elements" << std::endl;
[9150]184        return 1;
185    }
186
[9370]187    osg::ref_ptr<osgAnimation::TimelineAnimationManager> tl = new osgAnimation::TimelineAnimationManager(*animationManager);
[9371]188    root->setUpdateCallback(tl.get());
189   
[9150]190    ExampleTimelineUsage* callback = new ExampleTimelineUsage(tl.get());
[9370]191    root->setEventCallback(callback);
192    root->getUpdateCallback()->addNestedCallback(callback);
193       
[9150]194
195
196    // add the state manipulator
197    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
198   
199    // add the thread model handler
200    viewer.addEventHandler(new osgViewer::ThreadingHandler);
201
202    // add the window size toggle handler
203    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
204       
205    // add the stats handler
206    viewer.addEventHandler(new osgViewer::StatsHandler);
207
208    // add the help handler
209    viewer.addEventHandler(new osgViewer::HelpHandler(psr.getApplicationUsage()));
210
211    // add the LOD Scale handler
212    viewer.addEventHandler(new osgViewer::LODScaleHandler);
213
214    // add the screen capture handler
215    viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
216
[9370]217    viewer.setSceneData(root);
[9150]218
219    return viewer.run();
220}
221
Note: See TracBrowser for help on using the browser.