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

Revision 13488, 9.0 kB (checked in by robert, 5 hours ago)

Added in source shaders

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