Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
Interpolators Tutorial

In this tutorial you will learn how to use the various interpolator classes to generate splines and smooth aniamtions.

You can also use an interpolator to generate paths and silhouettes for the vl::Extrusion class.

Generated by showCatmullRomPentagonOpen() Generated by showCatmullRomPentagonClosed() Generated by showLinearPentagon() Generated by showInterpolatorAnimation()

[From App_Interpolators.cpp]

class App_Interpolators: public BaseDemo
{
public:
// Constructor.
App_Interpolators()
{
mTest = 0;
mLinearInterpolator = new vl::LinearInterpolatorFVec3;
mCatmullRomInterpolator = new vl::CatmullRomInterpolatorFVec3;
mTransform1 = new vl::Transform; // will follow linear interpolation
mTransform2 = new vl::Transform; // will follow Catmull-Rom interpolation
}
void initEvent()
{
vl::Log::notify(appletInfo());
rendering()->as<vl::Rendering>()->transform()->addChild(mTransform1.get());
rendering()->as<vl::Rendering>()->transform()->addChild(mTransform2.get());
showCatmullRomPentagonOpen();
showText();
}
void showCatmullRomPentagonOpen()
{
// generate the pentagon control points
std::vector<vl::fvec3> pentagon;
float radius = 5.0f;
for(int i=0; i<5; ++i)
{
float a = (float)i/5.0f*vl::fPi*2.0f + vl::fPi/2.0f;
pentagon.push_back(vl::fvec3(cos(a)*radius,sin(a)*radius,0));
}
// show the pentagon
showPath(pentagon, vl::green);
// Catmull-Rom interpolation over the pentagon control points
std::vector<vl::fvec3> pentagon_spline;
catmull.interpolator()->setPath( pentagon );
// automatically generate the appropriate Catmull-Rom spline end-points
catmull.interpolator()->setupEndPoints(false/*loop = no*/);
// sample the spline over 41 points
int segments = 41;
for(int i=0; i<segments; ++i)
{
float t = (float)i/(segments-1); // interpolate from 0.0 to 1.0 included
pentagon_spline.push_back( catmull.computePoint(t) );
}
// show the interpolated pentagon
showPath(pentagon_spline, vl::red, true/*show points*/);
}
void showCatmullRomPentagonLoop()
{
// generate the pentagon
std::vector<vl::fvec3> pentagon;
float radius = 5.0f;
for(int i=0; i<5; ++i)
{
float a = (float)i/5.0f*vl::fPi*2.0f + vl::fPi/2.0f;
pentagon.push_back(vl::fvec3(cos(a)*radius,sin(a)*radius,0));
}
showPath(pentagon, vl::green);
// Catmull-Rom interpolation over the pentagon
catmull.interpolator()->setPath( pentagon );
std::vector<vl::fvec3> pentagon_loop;
// automatically generate the appropriate Catmull-Rom spline end-points
catmull.interpolator()->setupEndPoints(true/*loop = yes*/);
int segments = 50;
for(int i=0; i<segments; ++i)
{
// interpolate from 0 to 0.9x, never reach 1.0 otherwise the last point would be the same as the first one
float t = (float)i/segments;
pentagon_loop.push_back( catmull.computePoint(t) );
}
showPath(pentagon_loop, vl::yellow, true/*show points*/, true/*close line loop*/);
}
void showLinearPentagon()
{
// generate the pentagon
std::vector<vl::fvec3> pentagon;
float radius = 5.0f;
for(int i=0; i<5; ++i)
{
float a = (float)i/5.0f*vl::fPi*2.0f + vl::fPi/2.0f;
pentagon.push_back(vl::fvec3(cos(a)*radius,sin(a)*radius,0));
}
showPath(pentagon, vl::green);
// linear interpolation over the pentagon
linear.interpolator()->setPath( pentagon );
std::vector<vl::fvec3> pentagon_linear;
int segments = 20; /* 21 would perfectly overlap the pentagon */
for(int i=0; i<segments; ++i)
{
// interpolate from 0 to 1.0
float t = (float)i/(segments-1);
pentagon_linear.push_back( linear.computePoint(t) );
}
vl::Actor* line = showPath(pentagon_linear, vl::blue, true/*show points*/);
// ensure the blue line is over the green one.
line->setRenderRank(1);
}
// creates two paths one linearly-interpolated and the other Catmull-Rom-interpolated
void showInterpolatorAnimation()
{
// generate a 5-points star.
std::vector<vl::fvec3> pentagon;
float radius = 5.0f;
for(int i=0; i<5; ++i)
{
float a = (float)i/5.0f*vl::fPi*2.0f*2.0f + vl::fPi/2.0f;
pentagon.push_back(vl::fvec3(cos(a)*radius,sin(a)*radius,0));
}
// Catmull-Rom interpolation over the star
mCatmullRomInterpolator->interpolator()->setPath( pentagon );
// generate line for visual feedback.
std::vector<vl::fvec3> pentagon_loop;
// automatically generate the appropriate Catmull-Rom spline end-points
mCatmullRomInterpolator->interpolator()->setupEndPoints(true/*loop = yes*/);
int segments = 50;
for(int i=0; i<segments; ++i)
{
// interpolate from 0 to 0.9x, never reach 1.0 otherwise the last point would be the same as the first one
float t = (float)i/segments;
pentagon_loop.push_back( mCatmullRomInterpolator->computePoint(t)*1.2f /*1.2f -> makes it a bit larger*/ );
}
showPath(pentagon_loop, vl::yellow, true/*show points*/, true/*close line loop*/);
// linear interpolation over the star (loop)
mLinearInterpolator->interpolator()->setPath( pentagon );
// close the pentagon
mLinearInterpolator->interpolator()->path().push_back(pentagon[0]);
// generate line for visual feedback.
std::vector<vl::fvec3> pentagon_linear;
segments = 20;
for(int i=0; i<segments; ++i)
{
// interpolate from 0 to 0.9x, never reach 1.0 otherwise the last point would be the same as the first one
float t = (float)i/segments;
pentagon_linear.push_back( mLinearInterpolator->computePoint(t) );
}
showPath(pentagon_linear, vl::blue, true/*show points*/, true/*close line loop*/);
// display animated arrows
vl::ref<vl::Geometry> arrow = vl::makePyramid(vl::vec3(0,0,0),0.5f,1.0f);
arrow->transform( vl::mat4::getRotation(-90.0f,1,0,0) );
arrow->computeNormals();
arrow_fx->shader()->enable(vl::EN_LIGHTING);
arrow_fx->shader()->setRenderState(new vl::Light, 0);
sceneManager()->tree()->addActor( arrow.get(), arrow_fx.get(), mTransform1.get() );
sceneManager()->tree()->addActor( arrow.get(), arrow_fx.get(), mTransform2.get() );
}
// displays a closed or open path, with or without points
vl::Actor* showPath(const std::vector<vl::fvec3>& ctrl_points, const vl::fvec4& color, bool points=false, bool loop=false)
{
// simple effect
effect->shader()->gocPointSize()->set(4);
effect->shader()->gocColor()->setValue(color);
// generates the line/points geometry
geom->setVertexArray( vert_array.get() );
vert_array->initFrom(ctrl_points);
geom->drawCalls().push_back(new vl::DrawArrays(loop ? vl::PT_LINE_LOOP : vl::PT_LINE_STRIP, 0, (int)vert_array->size()));
if (points)
geom->drawCalls().push_back(new vl::DrawArrays(vl::PT_POINTS, 0, (int)vert_array->size()));
// adds the geometry to the scene
return sceneManager()->tree()->addActor( geom.get(), effect.get(), NULL );
}
// Animates the arrows along the path.
void updateScene()
{
if (mTest == 3)
{
float delta = 1.0f/50.0f;
vl::fvec3 up(0,0,1);
// get the fractional part of the time to loop 0..1
float eye = vl::fract((float)vl::Time::currentTime() * 0.1f);
float look = vl::fract(eye+delta); // we have to remain in the range 0..1
// linear interpolation
m = vl::fmat4::getLookAtModeling(mLinearInterpolator->computePoint(eye),mLinearInterpolator->computePoint(look),up);
mTransform1->setLocalMatrix((vl::mat4)m);
// Catmull-Rom interpolation
m = vl::fmat4::getLookAtModeling(mCatmullRomInterpolator->computePoint(eye)*1.2f,mCatmullRomInterpolator->computePoint(look)*1.2f,up);
mTransform2->setLocalMatrix((vl::mat4)m);
}
}
// Press the left/right arrow buttons to navigate through the examples.
void keyPressEvent(unsigned short ch, vl::EKey key)
{
BaseDemo::keyPressEvent(ch,key);
if (key == vl::Key_Left || key == vl::Key_Right)
{
if (key == vl::Key_Left)
mTest--;
if (key == vl::Key_Right)
mTest++;
if (mTest < 0) mTest = 3;
if (mTest > 3) mTest = 0;
sceneManager()->tree()->actors()->clear();
switch(mTest)
{
case 0: showCatmullRomPentagonOpen(); break;
case 1: showCatmullRomPentagonLoop(); break;
case 2: showLinearPentagon(); break;
case 3: showInterpolatorAnimation(); break;
}
showText();
}
}
// displays the text
void showText()
{
text->setText("Press the left/right arrow keys to change test.");
text->setFont( vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 10) );
text->translate(0,-5,0);
text->setColor(vl::white);
effect->shader()->enable(vl::EN_BLEND);
sceneManager()->tree()->addActor(text.get(), effect.get());
}
protected:
int mTest;
};
// Have fun!