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]
Extrusion Tutorial

In this tutorial you will learn how to use the vl::Extrusion class to extrude a 2d silhouette along a 3d path in order to generate 3d geometries.

Remember that you can also use a vl::Interpolator to generate paths and silhouettes to be used with vl::Extrusion.

Generated by showSimplePipe() Generated by showFancyArch() Generated by showVortex() Generated by showNail()

[From App_Extrusion.cpp]

class App_Extrusion: public BaseDemo
{
public:
App_Extrusion(): mTest(0) {}
// Creates a simple extrusion
void showSimplePipe()
{
// Generates the actual extrusion
vl::Extrusion extrusion;
// Define the silhouette to be extruded: 24 sided circle
const int sides = 24;
const float radius = 1.0f;
for(int i=0; i<sides; ++i)
{
float t = (float)i/sides*vl::fPi*2.0f;
extrusion.silhouette().push_back(vl::fvec2(::cos(t)*radius, ::sin(t)*radius));
}
// Define the path along which the silhouette is extruded.
// Note: the first and last control points are not part of the actual extrusion
// but are used to define the orientation of the first and start segment.
extrusion.positionPath().push_back(vl::fvec3(-5, 0, 0) + vl::fvec3(-1,0,0));
extrusion.positionPath().push_back(vl::fvec3(-5, 0, 0));
extrusion.positionPath().push_back(vl::fvec3(-5, 5, 0));
extrusion.positionPath().push_back(vl::fvec3(+5, 5, 0));
extrusion.positionPath().push_back(vl::fvec3(+5, 0, 0));
extrusion.positionPath().push_back(vl::fvec3(+5, 0, 0) + vl::fvec3(+1,0,0));
// Setup the extrusion options.
extrusion.setSmooth(false);
extrusion.setFillBottom(true); // start of the extrusion is closed
extrusion.setFillTop(true); // end of the extrusion is closed
// Setup a simple white effect.
effect->shader()->setRenderState( new vl::Light, 0 );
// Generates the extrusion.
vl::ref<vl::Geometry> geom = extrusion.extrude();
sceneManager()->tree()->addActor( geom.get(), effect.get(), NULL );
// Utility function that visualizes the extrusion path.
showPath(extrusion.positionPath(),vl::red);
}
// Creates a fancy arch applying rotation and scaling to the extrusion
void showFancyArch()
{
// Generates the actual extrusion
vl::Extrusion extrusion;
// Define the silhouette to be extruded (a quad).
const int sides = 4;
const float radius = 1.0f;
for(int i=0; i<sides; ++i)
{
float t = (float)i/sides*vl::fPi*2.0f;
extrusion.silhouette().push_back(vl::fvec2(::cos(t)*radius, ::sin(t)*radius));
}
// Define the path along which the silhouette is extruded.
// Note: the first and last control points are not part of the actual extrusion
// but are used to define the orientation of the first and start segment.
extrusion.positionPath().push_back(vl::fvec3(-5, 0, 0) + vl::fvec3(0,-1,0));
extrusion.positionPath().push_back(vl::fvec3(-5, 0, 0));
for(int j=0; j<640; ++j)
{
float t = (float)j/(640-1)*vl::fPi;
extrusion.positionPath().push_back(vl::fvec3(-cos(t)*5, sin(t)*5, 0) + vl::fvec3(0,5,0));
}
extrusion.positionPath().push_back(vl::fvec3(+5, 0, 0));
extrusion.positionPath().push_back(vl::fvec3(+5, 0, 0) + vl::fvec3(0,-1,0));
// Defines a rotation key (in degrees) for each segment generated in order
// to rotate the silhouette along the extrusion path.
// Note that the segments generated are extrusion.positionPath().size()-2 as
// the first and last control points are not part of the actual extrusion
// but are used to define the orientation of the first and start segment.
for(unsigned i=0; i<extrusion.positionPath().size()-2; ++i)
{
float t = (float)i/(extrusion.positionPath().size()-2-1);
// rotate of 360*2 degrees (turns around twice)
extrusion.rotationPath().push_back(t*360.0f*2.0f);
}
// Defines a scaling key (in degrees) for each segment generated in order
// to rotate the silhouette along the extrusion path.
// Note that the segments generated are extrusion.positionPath().size()-2 as
// the first and last control points are not part of the actual extrusion
// but are used to define the orientation of the first and start segment.
for(unsigned i=0; i<extrusion.positionPath().size()-2; ++i)
{
float t = (float)i/(extrusion.positionPath().size()-2-1);
// make it smaller in the middle
float s = 1.0f - ::sin( t*vl::fPi )*0.8f;
extrusion.scalingPath().push_back(s);
}
// Setup the extrusion options.
extrusion.setSmooth(false);
extrusion.setFillBottom(false); // start of the extrusion is closed
extrusion.setFillTop(false); // end of the extrusion is closed
// Setup a simple white effect.
effect->shader()->setRenderState( new vl::Light, 0 );
// Generates the extrusion.
vl::ref<vl::Geometry> geom = extrusion.extrude();
sceneManager()->tree()->addActor( geom.get(), effect.get(), NULL );
// Utility function that visualizes the extrusion path.
showPath(extrusion.positionPath(),vl::red);
}
// Creates a vortex whose section is a flower.
void showVortex()
{
vl::Extrusion extrusion;
// Generate flower-like silhouette.
const int lati = 128;
for(int i=0; i<lati; ++i)
{
float t = (float)i/lati*vl::fPi*2.0f+3.14159365f/2.0f;
extrusion.silhouette().push_back(vl::fvec2(::cos(t)*0.4f, ::sin(t)*0.4f));
extrusion.silhouette().back() *= 2.0f + fabs(sin(t*8.0f)*2.0f-1.0f)*0.1f;
}
// Generate fancy vortex path.
float freq = 5.0f;
float width = 10.0f;
const int size = 250;
extrusion.positionPath().resize( size );
for(int i=0; i<size; ++i)
{
float t = (float)i/(size-1);
extrusion.positionPath()[i].y() = (t - 0.5f)*width;
float a = t * vl::fPi*2.0f*freq - vl::fPi/4.0f;
float s = ::sin( t*vl::fPi/2.0f );
s = 5.0f*s + 0.5f*(1.0f-s);
extrusion.positionPath()[i].x() = ::sin(a)*s;
extrusion.positionPath()[i].z() = ::cos(a)*s;
}
// Generate color path: linearly interpolate from blue to yellow.
for(int i=0; i<size-2; ++i)
{
float t = (float)i/(size-2-1);
vl::fvec4 c = vl::yellow*t + vl::blue*(1.0f-t);
extrusion.colorPath().push_back(c);
}
// Scaling factor along the vortex: starts small, ends big.
for(unsigned i=0; i<extrusion.positionPath().size()-2; ++i)
{
float t = (float)i/(extrusion.positionPath().size()-2-1);
float s = ::sin( t*vl::fPi/2.0f )*0.8f;
extrusion.scalingPath().push_back(s);
}
// Extrusion options.
extrusion.setSmooth(false);
extrusion.setFillBottom(true);
extrusion.setFillTop(true);
// Simple white effect.
effect->shader()->setRenderState( new vl::Light, 0 );
// Enable color material to visualize the generated vertex colors.
// Generates the actual extrusion.
vl::ref<vl::Geometry> extr = extrusion.extrude();
sceneManager()->tree()->addActor( extr.get(), effect.get(), NULL );
}
// Creates a vortex whose section is a flower.
void showNail()
{
vl::Extrusion extrusion;
// Defines the silhouette as a cross.
float diam = 1.0f;
extrusion.silhouette().push_back(vl::fvec2(-diam*3.0f,-diam));
extrusion.silhouette().push_back(vl::fvec2(-diam,-diam));
extrusion.silhouette().push_back(vl::fvec2(-diam,-diam*3.0f));
extrusion.silhouette().push_back(vl::fvec2(+diam,-diam*3.0f));
extrusion.silhouette().push_back(vl::fvec2(+diam,-diam));
extrusion.silhouette().push_back(vl::fvec2(+diam*3.0f,-diam));
extrusion.silhouette().push_back(vl::fvec2(+diam*3.0f,+diam));
extrusion.silhouette().push_back(vl::fvec2(+diam,+diam));
extrusion.silhouette().push_back(vl::fvec2(+diam,+diam*3.0f));
extrusion.silhouette().push_back(vl::fvec2(-diam,+diam*3.0f));
extrusion.silhouette().push_back(vl::fvec2(-diam,+diam));
extrusion.silhouette().push_back(vl::fvec2(-diam*3.0f,+diam));
// Extrusion path.
int segments = 500;
for(int i=0; i<segments; ++i)
{
float t = (float)i/(segments-1);
extrusion.positionPath().push_back( vl::fvec3( 0, t*20.0f-10.0f, 0) );
}
// Extrusion color.
for(int i=0; i<segments-2; ++i)
{
float t = (float)i/(segments-2-1);
vl::fvec4 c = vl::gold * t + vl::royalblue*(1.0f-t);
extrusion.colorPath().push_back(c);
}
// Extrusion color.
for(int i=0; i<segments-2; ++i)
{
float t = (float)i/(segments-2-1);
extrusion.scalingPath().push_back( t );
}
// Extrusion rotaion.
for(int i=0; i<segments-2; ++i)
{
float t = (float)i/(segments-2-1);
extrusion.rotationPath().push_back(360*t);
}
// Extrusion options.
extrusion.setSmooth(false);
extrusion.setFillBottom(true);
extrusion.setFillTop(true);
// Simple effect
effect->shader()->setRenderState( new vl::Light, 0 );
// Enable color material in order to see the generated vertex colors.
// Generates the actual extrusion.
vl::ref<vl::Geometry> geom = extrusion.extrude();
sceneManager()->tree()->addActor( geom.get(), effect.get(), NULL );
}
// Utility function to display a path
void showPath(const std::vector<vl::fvec3>& ctrl_points, const vl::fvec4& color)
{
// generate line geometry with lines and points
geom->setVertexArray( vert_array.get() );
vert_array->initFrom(ctrl_points);
geom->drawCalls().push_back(new vl::DrawArrays(vl::PT_LINE_STRIP, 0, (int)vert_array->size())); // lines
geom->drawCalls().push_back(new vl::DrawArrays(vl::PT_POINTS, 0, (int)vert_array->size())); // points
// setup simple effect
effect->shader()->gocColor()->setValue(color);
effect->shader()->gocPointSize()->set(3);
effect->shader()->gocLineStipple()->setPattern(0x3333);
effect->setRenderRank(1); // always draw over the pipe
sceneManager()->tree()->addActor( geom.get(), effect.get(), NULL );
}
// 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: showSimplePipe(); break;
case 1: showFancyArch(); break;
case 2: showVortex(); break;
case 3: showNail(); 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());
}
void initEvent()
{
vl::Log::notify(appletInfo());
showSimplePipe();
showText();
}
protected:
int mTest;
};
// Have fun!