# Visualization Library

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

[Home] [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.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 = ctrl_points;
        geom->setColor(color);
        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()->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::print(appletInfo());
        showSimplePipe();
        showText();
      }

    protected:
      int mTest;
    };

    // Have fun!

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:28.
Permission is granted to use this page to write and publish articles regarding Visualization Library.