diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3651704e5..5f649f180 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -112,6 +112,7 @@ IF(DYNAMIC_OPENSCENEGRAPH) ADD_SUBDIRECTORY(osgvertexprogram) ADD_SUBDIRECTORY(osgvolume) ADD_SUBDIRECTORY(osgwindows) + ADD_SUBDIRECTORY(osganimationhardware) ADD_SUBDIRECTORY(osganimationtimeline) ADD_SUBDIRECTORY(osganimationnode) ADD_SUBDIRECTORY(osganimationmakepath) diff --git a/examples/osganimationhardware/CMakeLists.txt b/examples/osganimationhardware/CMakeLists.txt new file mode 100644 index 000000000..28ee373a9 --- /dev/null +++ b/examples/osganimationhardware/CMakeLists.txt @@ -0,0 +1,3 @@ +SET(TARGET_SRC osganimationhardware.cpp ) +SET(TARGET_ADDED_LIBRARIES osgAnimation ) +SETUP_EXAMPLE(osganimationhardware) diff --git a/examples/osganimationhardware/osganimationhardware.cpp b/examples/osganimationhardware/osganimationhardware.cpp new file mode 100644 index 000000000..420387f64 --- /dev/null +++ b/examples/osganimationhardware/osganimationhardware.cpp @@ -0,0 +1,249 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + + +static unsigned int getRandomValueinRange(unsigned int v) +{ + return static_cast((rand() * 1.0 * v)/(RAND_MAX-1)); +} + + +osg::ref_ptr program; +// show how to override the default RigTransformHardware for customized usage +struct MyRigTransformHardware : public osgAnimation::RigTransformHardware +{ + bool init(osgAnimation::RigGeometry& geom) + { + osg::Vec3Array* pos = dynamic_cast(geom.getVertexArray()); + if (!pos) { + osg::notify(osg::WARN) << "RigTransformHardware no vertex array in the geometry " << geom.getName() << std::endl; + return false; + } + + if (!geom.getSkeleton()) { + osg::notify(osg::WARN) << "RigTransformHardware no skeleting set in geometry " << geom.getName() << std::endl; + return false; + } + + osgAnimation::Bone::BoneMap bm = geom.getSkeleton()->getBoneMap(); + + if (!createPalette(pos->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList())) + return false; + + int attribIndex = 11; + int nbAttribs = getNumVertexAttrib(); + + // use a global program for all avatar + if (!program.valid()) { + program = new osg::Program; + program->setName("HardwareSkinning"); + if (!_shader.valid()) + _shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"shaders/skinning.vert"); + + if (!_shader.valid()) { + osg::notify(osg::WARN) << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + + // replace max matrix by the value from uniform + { + std::string str = _shader->getShaderSource(); + std::string toreplace = std::string("MAX_MATRIX"); + std::size_t start = str.find(toreplace); + std::stringstream ss; + ss << getMatrixPaletteUniform()->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + _shader->setShaderSource(str); + osg::notify(osg::INFO) << "Shader " << str << std::endl; + } + + program->addShader(_shader.get()); + + for (int i = 0; i < nbAttribs; i++) + { + std::stringstream ss; + ss << "boneWeight" << i; + program->addBindAttribLocation(ss.str(), attribIndex + i); + + osg::notify(osg::INFO) << "set vertex attrib " << ss.str() << std::endl; + } + } + for (int i = 0; i < nbAttribs; i++) + { + std::stringstream ss; + ss << "boneWeight" << i; + geom.setVertexAttribData(attribIndex + i, osg::Geometry::ArrayData(getVertexAttrib(i),osg::Geometry::BIND_PER_VERTEX)); + } + + osg::ref_ptr ss = new osg::StateSet; + ss->addUniform(getMatrixPaletteUniform()); + ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex())); + ss->setAttributeAndModes(program.get()); + geom.setStateSet(ss.get()); + _needInit = false; + return true; + } + +}; + + +struct SetupRigGeometry : public osg::NodeVisitor +{ + bool _hardware; + SetupRigGeometry( bool hardware = true) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _hardware(hardware) {} + + void apply(osg::Geode& geode) + { + for (unsigned int i = 0; i < geode.getNumDrawables(); i++) + apply(*geode.getDrawable(i)); + } + void apply(osg::Drawable& geom) + { + if (_hardware) { + osgAnimation::RigGeometry* rig = dynamic_cast(&geom); + if (rig) + rig->setRigTransformImplementation(new MyRigTransformHardware); + } + + if (geom.getName() != std::string("BoundingBox")) // we disable compute of bounding box for all geometry except our bounding box + geom.setComputeBoundingBoxCallback(new osg::Drawable::ComputeBoundingBoxCallback); + } +}; + +osg::Group* createCharacterInstance(osg::Group* character, bool hardware) +{ + osg::ref_ptr c ; + if (hardware) + c = osg::clone(character, osg::CopyOp::DEEP_COPY_ALL & ~osg::CopyOp::DEEP_COPY_PRIMITIVES & ~osg::CopyOp::DEEP_COPY_ARRAYS); + else + c = osg::clone(character, osg::CopyOp::DEEP_COPY_ALL); + + osgAnimation::AnimationManagerBase* animationManager = dynamic_cast(c->getUpdateCallback()); + + osgAnimation::BasicAnimationManager* anim = dynamic_cast(animationManager); + const osgAnimation::AnimationList& list = animationManager->getAnimationList(); + int v = getRandomValueinRange(list.size()); + if (list[v]->getName() == std::string("MatIpo_ipo")) { + anim->playAnimation(list[v].get()); + v = (v + 1)%list.size(); + } + + anim->playAnimation(list[v].get()); + + SetupRigGeometry switcher(hardware); + c->accept(switcher); + + return c.release(); +} + + +int main (int argc, char* argv[]) +{ + std::cerr << "This example works better with nathan.osg" << std::endl; + + osg::ArgumentParser psr(&argc, argv); + + osgViewer::Viewer viewer(psr); + + bool hardware = true; + int maxChar = 10; + while (psr.read("--software")) { hardware = false; } + while (psr.read("--number", maxChar)) {} + + + osg::ref_ptr root = dynamic_cast(osgDB::readNodeFiles(psr)); + if (!root) + { + std::cout << psr.getApplicationName() <<": No data loaded" << std::endl; + return 1; + } + + { + osgAnimation::AnimationManagerBase* animationManager = dynamic_cast(root->getUpdateCallback()); + if(!animationManager) + { + osg::notify(osg::FATAL) << "no AnimationManagerBase found, updateCallback need to animate elements" << std::endl; + return 1; + } + } + + + osg::ref_ptr scene = new osg::Group; + + // add the state manipulator + viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); + + // add the thread model handler + viewer.addEventHandler(new osgViewer::ThreadingHandler); + + // add the window size toggle handler + viewer.addEventHandler(new osgViewer::WindowSizeHandler); + + // add the stats handler + viewer.addEventHandler(new osgViewer::StatsHandler); + + // add the help handler + viewer.addEventHandler(new osgViewer::HelpHandler(psr.getApplicationUsage())); + + // add the LOD Scale handler + viewer.addEventHandler(new osgViewer::LODScaleHandler); + + // add the screen capture handler + viewer.addEventHandler(new osgViewer::ScreenCaptureHandler); + + viewer.setSceneData(scene.get()); + + viewer.realize(); + + double xChar = maxChar; + double yChar = xChar * 9.0/16; + for (double i = 0.0; i < xChar; i++) { + for (double j = 0.0; j < yChar; j++) { + + osg::ref_ptr c = createCharacterInstance(root.get(), hardware); + osg::MatrixTransform* tr = new osg::MatrixTransform; + tr->setMatrix(osg::Matrix::translate( 2.0 * (i - xChar * .5), + 0.0, + 2.0 * (j - yChar * .5))); + tr->addChild(c.get()); + scene->addChild(tr); + } + } + std::cout << "created " << xChar * yChar << " instance" << std::endl; + + + return viewer.run(); +} + + diff --git a/examples/osganimationskinning/osganimationskinning.cpp b/examples/osganimationskinning/osganimationskinning.cpp index 277b6c779..66e81a3fd 100644 --- a/examples/osganimationskinning/osganimationskinning.cpp +++ b/examples/osganimationskinning/osganimationskinning.cpp @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or @@ -24,7 +24,6 @@ #include #include #include -#include #include osg::Geode* createAxis() diff --git a/examples/osganimationtimeline/osganimationtimeline.cpp b/examples/osganimationtimeline/osganimationtimeline.cpp index 58592b8da..129b6ef24 100644 --- a/examples/osganimationtimeline/osganimationtimeline.cpp +++ b/examples/osganimationtimeline/osganimationtimeline.cpp @@ -26,15 +26,19 @@ #include #include #include -#include #include #include #include +#include +#include +#include +#include + struct NoseBegin : public osgAnimation::Action::Callback { - virtual void operator()(osgAnimation::Action* action) + virtual void operator()(osgAnimation::Action* action, osgAnimation::ActionVisitor* nv) { std::cout << "sacrebleu, it scratches my nose, let me scratch it" << std::endl; std::cout << "process NoseBegin call back " << action->getName() << std::endl << std::endl; @@ -43,7 +47,7 @@ struct NoseBegin : public osgAnimation::Action::Callback struct NoseEnd : public osgAnimation::Action::Callback { - virtual void operator()(osgAnimation::Action* action) + virtual void operator()(osgAnimation::Action* action, osgAnimation::ActionVisitor* nv) { std::cout << "shhhrt shrrrrt shhhhhhrrrrt, haaa it's better"<< std::endl; std::cout << "process NoseEnd call back " << action->getName() << std::endl << std::endl; @@ -52,9 +56,9 @@ struct NoseEnd : public osgAnimation::Action::Callback struct ExampleTimelineUsage : public osgGA::GUIEventHandler { - osg::ref_ptr _mainLoop; - osg::ref_ptr _scratchHead; - osg::ref_ptr _scratchNose; + osg::ref_ptr _mainLoop; + osg::ref_ptr _scratchHead; + osg::ref_ptr _scratchNose; osg::ref_ptr _manager; bool _releaseKey; @@ -69,14 +73,14 @@ struct ExampleTimelineUsage : public osgGA::GUIEventHandler for (osgAnimation::AnimationList::const_iterator it = list.begin(); it != list.end(); it++) map[(*it)->getName()] = *it; - _mainLoop = new osgAnimation::StripAnimation(map["Idle_Main"].get(),0.0,0.0); + _mainLoop = new osgAnimation::ActionStripAnimation(map["Idle_Main"].get(),0.0,0.0); _mainLoop->setLoop(0); // means forever - _scratchHead = new osgAnimation::StripAnimation(map["Idle_Head_Scratch.02"].get(),0.2,0.3); + _scratchHead = new osgAnimation::ActionStripAnimation(map["Idle_Head_Scratch.02"].get(),0.2,0.3); _scratchHead->setLoop(1); // one time map["Idle_Nose_Scratch.01"]->setDuration(10.0); // set this animation duration to 10 seconds - _scratchNose = new osgAnimation::StripAnimation(map["Idle_Nose_Scratch.01"].get(),0.2,0.3); + _scratchNose = new osgAnimation::ActionStripAnimation(map["Idle_Nose_Scratch.01"].get(),0.2,0.3); _scratchNose->setLoop(1); // one time // add the main loop at priority 0 at time 0.