Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
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.setSilhouetteMode(vl::SilhouetteClosed); 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. vl::ref<vl::Effect> effect = new vl::Effect; effect->shader()->setRenderState( new vl::Light, 0 ); effect->shader()->enable(vl::EN_LIGHTING); effect->shader()->enable(vl::EN_DEPTH_TEST); // 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.setSilhouetteMode(vl::SilhouetteClosed); 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. vl::ref<vl::Effect> effect = new vl::Effect; effect->shader()->setRenderState( new vl::Light, 0 ); effect->shader()->enable(vl::EN_LIGHTING); effect->shader()->enable(vl::EN_DEPTH_TEST); // 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.setSilhouetteMode(vl::SilhouetteClosed); extrusion.setSmooth(false); extrusion.setFillBottom(true); extrusion.setFillTop(true); // Simple white effect. vl::ref<vl::Effect> effect = new vl::Effect; effect->shader()->setRenderState( new vl::Light, 0 ); effect->shader()->enable(vl::EN_LIGHTING); effect->shader()->enable(vl::EN_DEPTH_TEST); // Enable color material to visualize the generated vertex colors. effect->shader()->gocMaterial()->setColorMaterialEnabled(true); // 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.setSilhouetteMode(vl::SilhouetteClosed); extrusion.setSmooth(false); extrusion.setFillBottom(true); extrusion.setFillTop(true); // Simple effect vl::ref<vl::Effect> effect = new vl::Effect; effect->shader()->setRenderState( new vl::Light, 0 ); effect->shader()->enable(vl::EN_LIGHTING); effect->shader()->enable(vl::EN_DEPTH_TEST); // Enable color material in order to see the generated vertex colors. effect->shader()->gocMaterial()->setColorMaterialEnabled(true); // 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 vl::ref<vl::Geometry> geom = new vl::Geometry; vl::ref<vl::ArrayFloat3> vert_array = new vl::ArrayFloat3; 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 vl::ref<vl::Effect> effect = new vl::Effect; effect->shader()->gocColor()->setValue(color); effect->shader()->enable(vl::EN_LINE_STIPPLE); 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() { vl::ref<vl::Text> text = new vl::Text; text->setText("Press the left/right arrow keys to change test."); text->setFont( vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 10) ); text->setAlignment( vl::AlignHCenter | vl::AlignTop ); text->setViewportAlignment( vl::AlignHCenter | vl::AlignTop ); text->translate(0,-5,0); text->setColor(vl::white); vl::ref<vl::Effect> effect = new vl::Effect; 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!