Hi Cedric,

I tried to create a simple project based on the 'osganimationmorph' demo as Robert Osfield suggested.

Instead of loading the geometries from a *.osg file, I define two new geometries (both quads but on a different position). These geometries are added as a drawable to the MorphGeometry. However, for some reason OSG doesn't allows me to swap the old geom0 and geom1 geometry objects with the ones I create. The application crashes when you try to run it.

Any suggestions?

Kind regards,
- Laurence


Cedric Pinson wrote:
<div class="moz-text-flowed" style="font-family: -moz-fixed">Hi Laurence,

You can easily do it with morphgeometry:
- define two geometry with morphgeometry
- use an custom update callback that use an ease motion to control the ratio of geometry to use

Would be great to make an example with it, it will help others users.

Cheers,
Cedric

Laurence Muller wrote:
Hi,

In the application I am working on, I am trying to create a smooth (transition) animation on the vertices inside an object.

Example:
I have included an illustration to make my problem a bit more clear. The current scene contains one geode with a geometry attached. The geometry is filled with 7 quads (4 vertices per quad) and is illustrated as red dots in the picture. (The 'edges' are stored in a separate geode)

The application allows users to select a specific layout (radial, force based, etc) for the quads. In the current implementation this change happens immediately. (It updates the vertex array with new values and uses the dirty() call on the vertex array).

On the OSG wiki page I found some information about animating objects in the scene graph. http://www.openscenegraph.org/projects/osg/wiki/Community/NodeKits/osgAnimation
http://www.robertpenner.com/easing/easing_demo.html

However, it seems like this will only work on geode level (by modifying the Matrix or PositionAttitudeTransformation). Another problem with this method is that it seems that you need to create a predefined animation.

In my case the new position of a vertex will depend on the current position (and the animation only needs to be used once).

Question:
- Is there a way to use the osgAnimation functions on the vertex array and is it possible to use it with the transition methods from the EaseMotion demo?

Kind regards,
- Laurence

------------------------------------------
Laurence Muller
Website/Blog/Portfolio:
http://www.multigesture.net/


------------------------------------------------------------------------

------------------------------------------------------------------------

_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org



--
------------------------------------------
Laurence Muller (M.Sc.)
Informatics Institute, Faculty of Science, Universiteit van Amsterdam.
Science Park 107, 1098 XG Amsterdam, The Netherlands

Website/Blog/Portfolio:
1. http://www.multigesture.net/
2. http://www.science.uva.nl/~lmuller/

E-mail: [email protected]

#include <iostream>
#include <osg/Geometry>
#include <osg/MatrixTransform>
#include <osg/Geode>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osgUtil/SmoothingVisitor>
#include <osg/io_utils>

#include <osgAnimation/MorphGeometry>
#include <osgAnimation/BasicAnimationManager>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

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<osgViewer::View*>(&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<osg::Geometry> _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<osg::Geometry*>(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;
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to