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