#include #include #include #include #include #include #include #include #include #include #include #include #include #include osgAnimation::Animation* animation; osgAnimation::BasicAnimationManager* bam; // Mouse/Keyboard event handler class PickHandler : public osgGA::GUIEventHandler { public: PickHandler() {} ~PickHandler() {} bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa); }; bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa) { switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::PUSH): { osgViewer::View* view = dynamic_cast(&aa); // do smth with mouse. disabled for now. return false; } case(osgGA::GUIEventAdapter::KEYDOWN): { if (ea.getKey()=='a') { // Play animation bam->playAnimation(animation); } return false; } default: return false; } } // Geometry loader struct GeometryFinder : public osg::NodeVisitor { osg::ref_ptr _geom; GeometryFinder() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} void apply(osg::Geode& geode) { if (_geom.valid()) return; for (unsigned int i = 0; i < geode.getNumDrawables(); i++) { osg::Geometry* geom = dynamic_cast(geode.getDrawable(i)); if (geom) { _geom = geom; return; } } } }; // Geometry loader osg::Geometry* getShape(const std::string& name) { osg::Node* shape0 = osgDB::readNodeFile(name); GeometryFinder finder; shape0->accept(finder); return finder._geom.get(); } int main (int argc, char* argv[]) { osg::ArgumentParser arguments(&argc, argv); osgViewer::Viewer viewer(arguments); animation = new osgAnimation::Animation; osgAnimation::FloatLinearChannel* channel0 = new osgAnimation::FloatLinearChannel; channel0->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(0,0.0)); channel0->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(1,1.0)); channel0->setTargetName("MorphNodeCallback"); channel0->setName("0"); osgAnimation::FloatLinearChannel* channel1 = new osgAnimation::FloatLinearChannel; channel1->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(0,1.0)); channel1->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::FloatKeyframe(1,0.0)); channel1->setTargetName("MorphNodeCallback"); channel1->setName("1"); animation->addChannel(channel0); animation->addChannel(channel1); animation->setName("Morph"); animation->computeDuration(); //animation->setPlaymode(osgAnimation::Animation::PPONG); animation->setPlaymode(osgAnimation::Animation::ONCE); // Just play it once... bam = new osgAnimation::BasicAnimationManager; bam->registerAnimation(animation); // Create 2 geometries... // Is this really needed? We only want to modify the position of a vertex in a drawable... // State A (Just a simple quad for now) osg::Geometry* geom0 = new osg::Geometry; osg::Vec3Array* verts0 = new osg::Vec3Array; osg::Vec4Array* colors0 = new osg::Vec4Array; geom0->setName("StateA"); double x = 0, y = 0, w = 10, h = 15; verts0->push_back(osg::Vec3(x + w, 0, y + h)); // top right verts0->push_back(osg::Vec3(x, 0, y + h)); // top left verts0->push_back(osg::Vec3(x, 0, y)); // bottom left verts0->push_back(osg::Vec3(x + w, 0, y)); // bottom right colors0->push_back(osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f)); colors0->push_back(osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f)); colors0->push_back(osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f)); colors0->push_back(osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f)); geom0->setVertexArray(verts0); geom0->setColorArray(colors0); geom0->setColorBinding(osg::Geometry::BIND_PER_VERTEX); geom0->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4)); // State B osg::Geometry* geom1 = new osg::Geometry; osg::Vec3Array* verts1 = new osg::Vec3Array; osg::Vec4Array* colors1 = new osg::Vec4Array; geom0->setName("StateB"); x = 50; y = 0; w = 20; h = 30; verts1->push_back(osg::Vec3(x + w, 0, y + h)); // top right verts1->push_back(osg::Vec3(x, 0, y + h)); // top left verts1->push_back(osg::Vec3(x, 0, y)); // bottom left verts1->push_back(osg::Vec3(x + w, 0, y)); // bottom right colors1->push_back(osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f)); colors1->push_back(osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f)); colors1->push_back(osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f)); colors1->push_back(osg::Vec4 (1.0f, 0.0f, 0.0f, 1.0f)); geom1->setVertexArray(verts1); geom1->setColorArray(colors1); geom1->setColorBinding(osg::Geometry::BIND_PER_VERTEX); geom1->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4)); /* // Using osg data sets to morph from shape0 to shape1 // this works... osg::Geometry* geom0 = getShape("morphtarget_shape0.osg"); if (!geom0) { std::cerr << "can't read morphtarget_shape0.osg" << std::endl; return 0; } osg::Geometry* geom1 = getShape("morphtarget_shape1.osg"); if (!geom1) { std::cerr << "can't read morphtarget_shape1.osg" << std::endl; return 0; } */ // initialize with the first shape osgAnimation::MorphGeometry* morph = new osgAnimation::MorphGeometry(*geom0); morph->addMorphTarget(geom0); morph->addMorphTarget(geom1); osg::Group* scene = new osg::Group; scene->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); scene->addUpdateCallback(bam); osg::Geode* geode = new osg::Geode; geode->addDrawable(morph); geode->addUpdateCallback(new osgAnimation::UpdateMorph("MorphNodeCallback")); scene->addChild(geode); // Viewer settings viewer.addEventHandler(new osgViewer::StatsHandler()); viewer.addEventHandler(new osgViewer::WindowSizeHandler()); viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); viewer.setCameraManipulator(new osgGA::TrackballManipulator()); viewer.addEventHandler(new PickHandler()); // press a to start animation // let's run ! viewer.setSceneData( scene ); viewer.setUpViewInWindow(40, 40, 1024, 768, 0); viewer.realize(); while (!viewer.done()) { viewer.frame(); } //osgDB::writeNodeFile(*scene, "morph_scene.osg"); return 0; }