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

Revision 10923, 8.6 kB (checked in by robert, 5 years ago)

Fixed warnings

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