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

Revision 10697, 8.5 kB (checked in by robert, 4 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 
[10697]1/*  -*-c++-*-
2 *  Copyright (C) 2009 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#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#include <osg/Drawable>
26
27#include <osgAnimation/BasicAnimationManager>
28#include <osgAnimation/RigGeometry>
29#include <osgAnimation/RigTransformHardware>
30#include <osgAnimation/AnimationManagerBase>
31
32#include <sstream>
33
34
35static unsigned int getRandomValueinRange(unsigned int v)
36{
37    return static_cast<unsigned int>((rand() * 1.0 * v)/(RAND_MAX-1));
38}
39
40
41osg::ref_ptr<osg::Program> program;
42// show how to override the default RigTransformHardware for customized usage
43struct MyRigTransformHardware : public osgAnimation::RigTransformHardware
44{
45    bool init(osgAnimation::RigGeometry& geom)
46    {
47        osg::Vec3Array* pos = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
48        if (!pos) {
49            osg::notify(osg::WARN) << "RigTransformHardware no vertex array in the geometry " << geom.getName() << std::endl;
50            return false;
51        }
52
53        if (!geom.getSkeleton()) {
54            osg::notify(osg::WARN) << "RigTransformHardware no skeleting set in geometry " << geom.getName() << std::endl;
55            return false;
56        }
57
58        osgAnimation::Bone::BoneMap bm = geom.getSkeleton()->getBoneMap();
59
60        if (!createPalette(pos->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList()))
61            return false;
62
63        int attribIndex = 11;
64        int nbAttribs = getNumVertexAttrib();
65
66        // use a global program for all avatar
67        if (!program.valid()) {
68            program = new osg::Program;
69            program->setName("HardwareSkinning");
70            if (!_shader.valid())
71                _shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"shaders/skinning.vert");
72
73            if (!_shader.valid()) {
74                osg::notify(osg::WARN) << "RigTransformHardware can't load VertexShader" << std::endl;
75                return false;
76            }
77
78            // replace max matrix by the value from uniform
79            {
80                std::string str = _shader->getShaderSource();
81                std::string toreplace = std::string("MAX_MATRIX");
82                std::size_t start = str.find(toreplace);
83                std::stringstream ss;
84                ss << getMatrixPaletteUniform()->getNumElements();
85                str.replace(start, toreplace.size(), ss.str());
86                _shader->setShaderSource(str);
87                osg::notify(osg::INFO) << "Shader " << str << std::endl;
88            }
89
90            program->addShader(_shader.get());
91
92            for (int i = 0; i < nbAttribs; i++)
93            {
94                std::stringstream ss;
95                ss << "boneWeight" << i;
96                program->addBindAttribLocation(ss.str(), attribIndex + i);
97
98                osg::notify(osg::INFO) << "set vertex attrib " << ss.str() << std::endl;
99            }
100        }
101        for (int i = 0; i < nbAttribs; i++)
102        {
103            std::stringstream ss;
104            ss << "boneWeight" << i;
105            geom.setVertexAttribData(attribIndex + i, osg::Geometry::ArrayData(getVertexAttrib(i),osg::Geometry::BIND_PER_VERTEX));
106        }
107
108        osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
109        ss->addUniform(getMatrixPaletteUniform());
110        ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex()));
111        ss->setAttributeAndModes(program.get());
112        geom.setStateSet(ss.get());
113        _needInit = false;
114        return true;
115    }
116
117};
118
119
120struct SetupRigGeometry : public osg::NodeVisitor
121{
122    bool _hardware;
123    SetupRigGeometry( bool hardware = true) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _hardware(hardware) {}
124   
125    void apply(osg::Geode& geode)
126    {
127        for (int i = 0; i < geode.getNumDrawables(); i++)
128            apply(*geode.getDrawable(i));
129    }
130    void apply(osg::Drawable& geom)
131    {
132        if (_hardware) {
133            osgAnimation::RigGeometry* rig = dynamic_cast<osgAnimation::RigGeometry*>(&geom);
134            if (rig)
135                rig->setRigTransformImplementation(new MyRigTransformHardware);
136        }
137
138        if (geom.getName() != std::string("BoundingBox")) // we disable compute of bounding box for all geometry except our bounding box
139            geom.setComputeBoundingBoxCallback(new osg::Drawable::ComputeBoundingBoxCallback);
140    }
141};
142
143osg::Group* createCharacterInstance(osg::Group* character, bool hardware)
144{
145    osg::ref_ptr<osg::Group> c ;
146    if (hardware)
147        c = osg::clone(character, osg::CopyOp::DEEP_COPY_ALL & ~osg::CopyOp::DEEP_COPY_PRIMITIVES & ~osg::CopyOp::DEEP_COPY_ARRAYS);
148    else
149        c = osg::clone(character, osg::CopyOp::DEEP_COPY_ALL);
150
151    osgAnimation::AnimationManagerBase* animationManager = dynamic_cast<osgAnimation::AnimationManagerBase*>(c->getUpdateCallback());
152
153    osgAnimation::BasicAnimationManager* anim = dynamic_cast<osgAnimation::BasicAnimationManager*>(animationManager);
154    const osgAnimation::AnimationList& list = animationManager->getAnimationList();
155    int v = getRandomValueinRange(list.size());
156    if (list[v]->getName() == std::string("MatIpo_ipo")) {
157        anim->playAnimation(list[v].get());
158        v = (v + 1)%list.size();
159    }
160       
161    anim->playAnimation(list[v].get());
162
163    SetupRigGeometry switcher(hardware);
164    c->accept(switcher);
165
166    return c.release();
167}
168
169
170int main (int argc, char* argv[])
171{
172    std::cerr << "This example works better with nathan.osg" << std::endl;
173
174    osg::ArgumentParser psr(&argc, argv);
175
176    osgViewer::Viewer viewer(psr);
177
178    bool hardware = true;
179    int maxChar = 10;
180    while (psr.read("--software")) { hardware = false; }
181    while (psr.read("--number", maxChar)) {}
182
183
184    osg::ref_ptr<osg::Group> root = dynamic_cast<osg::Group*>(osgDB::readNodeFiles(psr));
185    if (!root)
186    {
187        std::cout << psr.getApplicationName() <<": No data loaded" << std::endl;
188        return 1;
189    }
190
191    {
192        osgAnimation::AnimationManagerBase* animationManager = dynamic_cast<osgAnimation::AnimationManagerBase*>(root->getUpdateCallback());
193        if(!animationManager)
194        {
195            osg::notify(osg::FATAL) << "no AnimationManagerBase found, updateCallback need to animate elements" << std::endl;
196            return 1;
197        }
198    }
199
200
201    osg::ref_ptr<osg::Group> scene = new osg::Group;
202
203    // add the state manipulator
204    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
205   
206    // add the thread model handler
207    viewer.addEventHandler(new osgViewer::ThreadingHandler);
208
209    // add the window size toggle handler
210    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
211       
212    // add the stats handler
213    viewer.addEventHandler(new osgViewer::StatsHandler);
214
215    // add the help handler
216    viewer.addEventHandler(new osgViewer::HelpHandler(psr.getApplicationUsage()));
217
218    // add the LOD Scale handler
219    viewer.addEventHandler(new osgViewer::LODScaleHandler);
220
221    // add the screen capture handler
222    viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
223
224    viewer.setSceneData(scene);
225
226    viewer.realize();
227
228    int xChar = maxChar;
229    int yChar = xChar * 9.0/16;
230    for (int i = 0; i < xChar; i++) {
231        for (int j = 0; j < yChar; j++) {
232
233            osg::ref_ptr<osg::Group> c = createCharacterInstance(root.get(), hardware);
234            osg::MatrixTransform* tr = new osg::MatrixTransform;
235            tr->setMatrix(osg::Matrix::translate( 2 * (i - xChar * .5),
236                                                  0,
237                                                  2 * (j - yChar * .5)));
238            tr->addChild(c);
239            scene->addChild(tr);
240        }
241    }
242    std::cout << "created " << xChar * yChar << " instance"  << std::endl;
243
244
245    return viewer.run();
246}
247
Note: See TracBrowser for help on using the browser.