virtual void initEvent()
  {
    if (!GLEW_ARB_multitexture)
    {
      vl::Log::error("GL_ARB_multitexture required.\n");
      openglContext()->quitApplication();
      return;
    }
    vl::Log::print(appletInfo());

    ghostCameraManipulator()->setMovementSpeed(5);
    // allocate terrain scene manager
    vl::ref<vl::Terrain> terrain = new vl::Terrain;
    // use GLSL?
    terrain->setUseGLSL( GLEW_ARB_shading_language_100 ? true : false );
    // dimensions of the terrain
    terrain->setWidth(100);
    terrain->setDepth(100);
    terrain->setHeight(5.0f);
    // heightmap texture size used by the GLSL program
    if (GLEW_ATI_texture_float || GLEW_ARB_texture_float)
      terrain->setHeightmapTextureFormat(vl::TF_LUMINANCE16F);
    else
      terrain->setHeightmapTextureFormat(vl::TF_LUMINANCE);
    // origin of the terrain
    terrain->setOrigin(vl::vec3(0,0,0));
    // define textures
    terrain->setHeightmapTexture("/images/ps_height_4k.jpg");
    terrain->setTerrainTexture("/images/ps_texture_4k.jpg");
    terrain->setDetailTexture("/images/noise.png");
    terrain->setDetailRepetitionCount(8);
    // define shaders to be used to render the terrain
    terrain->setFragmentShader("/glsl/terrain.fs");
    terrain->setVertexShader("/glsl/terrain.vs");
    // initialize the terrain
    terrain->init();
    // add the terrain scene manager to the rendering
    rendering()->as<vl::Rendering>()->sceneManagers()->push_back( terrain.get() );

    // adds fog if we are not using GLSL but the fixed function pipeline
    if (!terrain->useGLSL())
    {
      // set sky to white
      rendering()->as<vl::Rendering>()->camera()->viewport()->setClearColor(vl::white);
      // set fog render state
      vl::ref<vl::Fog> fog = new vl::Fog;
      fog->setColor(vl::white);
      fog->setDensity(0.045f);
      fog->setMode(vl::FM_EXP);
      // install and enable fog
      terrain->shaderNode()->setRenderState(fog.get());
      terrain->shaderNode()->setEnable(vl::EN_FOG,true);
      terrain->shaderNode()->updateHierarchy();
    }

    // for debugging purposes
    #if 0
      showBoundingVolumes(1,0);
    #endif
  }
  virtual void initEvent()
  {
    vl::Log::print(appletInfo());

    srand((int)time(NULL));

    // populate our scene with some random objects

    vl::ref<vl::Effect> fx = new vl::Effect;
    fx->shader()->enable(vl::EN_DEPTH_TEST);
    fx->shader()->enable(vl::EN_LIGHTING);
    fx->shader()->gocLight(0)->setLinearAttenuation(0.025f);
    fx->shader()->gocMaterial()->setColorMaterialEnabled(true);

    int   count    = 1;
    float displace = 2.0f;
    for(int z=-count; z<=count; ++z)
    for(int y=-count; y<=count; ++y)
    for(int x=-count; x<=count; ++x)
    {
      vl::ref<vl::Geometry> geom = randomObject();
      vl::Actor* act = sceneManager()->tree()->addActor( geom.get(), fx.get(), new vl::Transform );
      act->setObjectName(geom->objectName());
      act->transform()->translate(x*displace, y*displace, z*displace);
      act->transform()->computeWorldMatrix();
    }

    // create a uv-sphere used to highlight the intersection point

    vl::ref<vl::Geometry> intersection_point_geom = vl::makeUVSphere(vl::vec3(0,0,0), 0.1f);
    intersection_point_geom->computeNormals();
    intersection_point_geom->setColor(vl::green);
    vl::Actor* intersection_point_act = sceneManager()->tree()->addActor( intersection_point_geom.get(), fx.get(), new vl::Transform );
    mIntersectionPoint = intersection_point_act->transform();
  }
    virtual void initEvent()
    {
        vl::Log::notify(appletInfo());

        trackball()->setTransform(NULL);

        // setup texture
        vl::ref<vl::Image> img = vl::loadImage("/volume/VLTest.dat")->convertFormat(vl::IF_LUMINANCE);

        vl::ref<vl::Actor> splat_actor = new vl::Actor;
        splat_actor->actorEventCallbacks()->push_back( new vl::DepthSortCallback );
        init_LUMINANCE_UBYTE( splat_actor.get(), img.get(), vl::fvec3(10,10,10), 80, 255, TransferRGBA_255() );

        vl::ref<vl::Effect> fx = new vl::Effect;

        fx->shader()->enable(vl::EN_LIGHTING);
        fx->shader()->setRenderState( new vl::Light, 0 );
        fx->shader()->gocLightModel()->setTwoSide(true);
        // enable color material if you want to see per-point colors
        fx->shader()->gocMaterial()->setColorMaterialEnabled(true);
        fx->shader()->enable( vl::EN_BLEND );
        fx->shader()->enable(vl::EN_POINT_SMOOTH);
        fx->shader()->gocPointSize()->set(1.5f);
        splat_actor->setEffect(fx.get());

        sceneManager()->tree()->addActor( splat_actor.get() );

    }
  void initEvent()
  {
    vl::Log::notify(appletInfo());

    if(!vl::Has_Occlusion_Query)
    {
      vl::Log::error("No support to hardware occlusion culling found!\n");
      vl::Time::sleep(2000);
      exit(1);
    }

    // #######################################################################
    // # These 4 lines are the only code needed to enable occlusion culling, #
    // # no special sorter or render rank/block setup needed!                #
    // #######################################################################

    // wraps the regular renderer inside the occlusion renderer
    vl::Renderer* regular_renderer = rendering()->as<vl::Rendering>()->renderer();
    // creates our occlusion renderer
    mOcclusionRenderer = new vl::OcclusionCullRenderer;
    mOcclusionRenderer->setWrappedRenderer( regular_renderer );
    // installs the occlusion renderer in place of the regular one
    rendering()->as<vl::Rendering>()->setRenderer( mOcclusionRenderer.get() );

    // note: to disable occlusion culling just restore the 'regular_renderer' as we do below in 'keyPressEvent()'

    populateScene();
  }
  void initEvent()
  {
    vl::Log::notify(appletInfo());

    // load model
    vl::ref<vl::Geometry> model = vl::loadResource("/models/3ds/monkey.3ds")->get<vl::Geometry>(0);
    model->computeNormals();

    // install transform
    mClipTr = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(mClipTr.get());

    // to be used later
    vl::ref<vl::Light> light = new vl::Light;

    // demonstrates multipassing clipping

    vl::ref<vl::Effect> clip_fx  = new vl::Effect;
    vl::ref<vl::Shader> clip1_sh = new vl::Shader; 
    vl::ref<vl::Shader> clip2_sh = new vl::Shader;
    // setup clipping pass 1
    clip1_sh->setRenderState( light.get(), 0 );
    clip1_sh->enable(vl::EN_LIGHTING);
    clip1_sh->enable(vl::EN_DEPTH_TEST);
    clip1_sh->gocMaterial()->setBackDiffuse(vl::yellow);
    clip1_sh->gocLightModel()->setTwoSide(true);
    // clipping plane 1 setup
    clip1_sh->gocClipPlane(0)->setPlane( vl::Plane(0.2f, vl::vec3(0,+1,0)) );
    clip1_sh->gocClipPlane(0)->bindTransform( mClipTr.get() );
    // setup clipping pass 2
    clip2_sh->setRenderState( light.get(), 0 );
    clip2_sh->enable(vl::EN_LIGHTING);
    clip2_sh->enable(vl::EN_DEPTH_TEST);
    clip2_sh->gocMaterial()->setBackDiffuse(vl::green);
    clip2_sh->gocLightModel()->setTwoSide(true);
    // clipping plane 2 setup
    clip2_sh->gocClipPlane(0)->setPlane( vl::Plane(0.2f, vl::vec3(0,-1,0)) );
    clip2_sh->gocClipPlane(0)->bindTransform( mClipTr.get() );
    // install the two passes for LOD 0
    clip_fx->setLOD(0, clip1_sh.get(), clip2_sh.get());
    // add model to the scene
    sceneManager()->tree()->addActor( model.get(), clip_fx.get(), NULL );

    // renders a plane for visual feedback

    // setup effect
    vl::ref<vl::Effect> plane_fx = new vl::Effect;
    plane_fx->setRenderRank(1); // draw after the clipped model
    plane_fx->shader()->enable(vl::EN_DEPTH_TEST);
    plane_fx->shader()->enable(vl::EN_BLEND);
    plane_fx->shader()->gocLightModel()->setTwoSide(true);
    plane_fx->shader()->gocColor()->setValue(vl::fvec4(1,0,0,0.3f)); // transparent red
    // add plane actor
    vl::ref<vl::Geometry> plane = vl::makeGrid( vl::vec3(0,0,0), 4,4, 2,2 );
    sceneManager()->tree()->addActor( plane.get(), plane_fx.get(), mClipTr.get() );
  }
  // initialization
  void initEvent()
  {
    vl::Log::notify(appletInfo());
    srand((unsigned int)time(NULL));

    generateTrees (100.0f, 500);
    generateStars (100.0f, 500);
    generateGround(100.0f);
    generateLunapark();
  }
  virtual void initEvent()
  {
    vl::Log::print(appletInfo());

    trackball()->setTransform(rendering()->as<vl::Rendering>()->transform());

    mMipmappingOn = true;
    mLodBias = 0.0;

    multitexturing();
    textureRectangle();
    texture3D();
    texture2DArray();
    texture1DArray();
    sphericalMapping();
    cubeMapping();
  }
  /* initialization */
  void initEvent()
  {
    vl::Log::notify(appletInfo());

    /* initialize the text actor */
    mText->setText("Drop a MOL2 file inside the window.");
    mText->setFont( vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 10) );
    mText->setAlignment( vl::AlignHCenter | vl::AlignTop );
    mText->setViewportAlignment( vl::AlignHCenter | vl::AlignTop );
    mText->setTextAlignment(vl::TextAlignCenter);
    mText->translate(0,-5,0);
    mText->setColor(vl::white);
    vl::ref<vl::Effect> effect = new vl::Effect;
    effect->shader()->enable(vl::EN_BLEND);
    sceneManager()->tree()->addActor(mText.get(), effect.get());

    loadMolecule("/mol/molecule.mol2");
  }
  void initEvent()
  {
    // Basic initialization
    vl::Log::print(appletInfo());

    // Filled effect
    vl::ref<vl::Effect> filled_fx = new vl::Effect;

    // Wireframe effect
    vl::ref<vl::Effect> wireframe_fx = new vl::Effect;
    wireframe_fx->shader()->gocPolygonMode()->set(vl::PM_LINE,vl::PM_LINE);

    // Add empty Actors
    mStar1 = sceneManager()->tree()->addActor( new vl::Actor(NULL, filled_fx.get(), new vl::Transform) );
    mStar2 = sceneManager()->tree()->addActor( new vl::Actor(NULL, wireframe_fx.get(), new vl::Transform) );
    rendering()->as<vl::Rendering>()->transform()->addChild(mStar1->transform());
    rendering()->as<vl::Rendering>()->transform()->addChild(mStar2->transform());
  }
  virtual void initEvent()
  {
    vl::Log::notify(appletInfo());

    vl::ref<vl::Effect> fx = new vl::Effect;
    fx->shader()->enable(vl::EN_LIGHTING);
    fx->shader()->setRenderState( new vl::Light, 0 );
    fx->shader()->enable(vl::EN_DEPTH_TEST);

    // vl::ref<vl::Texture> texture = new vl::Texture("/images/world.topo.bathy.200406.3x8192x4096.png");
    vl::ref<vl::Texture> texture = new vl::Texture("/images/world.topo.bathy.200406.3x2048x1024.png");
    // vl::ref<vl::Texture> texture = new vl::Texture("/images/land_lights_16384.tif");
    // vl::ref<vl::Texture> texture = new vl::Texture("/images/land_ocean_ice_cloud_8192.tif");

    fx->shader()->gocTextureSampler(0)->setTexture(texture.get());

    //vl::ref<vl::Shader> wire = new vl::Shader;
    //wire->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE);
    //wire->gocPolygonOffset()->set(-1, -1);
    //wire->enable(vl::EN_POLYGON_OFFSET_LINE);
    //wire->enable(vl::EN_DEPTH_TEST);
    //fx->lod(0)->push_back(wire.get());

    float dx = 0.5f / texture->width();
    float dy = 0.5f / texture->height();
    vl::ref<vl::Geometry> earth = vl::makeGrid( vl::vec3(0,0,0), vl::fPi*2.0f, vl::fPi, 40, 40, true, vl::fvec2(dx,dy), vl::fvec2(1-dx,1-dy) );
    vl::ArrayFloat3* coord3 = vl::cast<vl::ArrayFloat3>( earth->vertexArray() );
    vl::ref<vl::ArrayFloat3> norm3 = new vl::ArrayFloat3;
    earth->setNormalArray(norm3.get());
    norm3->resize(coord3->size());
    for(size_t i=0; i<coord3->size(); ++i)
    {
      float longitude = coord3->at(i).x();
      float latitude  = coord3->at(i).z();
      coord3->at(i)   = vl::fmat4::getRotation(longitude*vl::fRAD_TO_DEG, 0,-1,0) * vl::fmat4::getRotation(latitude*vl::fRAD_TO_DEG, 1,0,0) * vl::fvec3(0,0,1);
      norm3->at(i)    = coord3->at(i);
      norm3->at(i).normalize();
    }

    sceneManager()->tree()->addActor(earth.get(), fx.get());
  }
    virtual void initEvent()
    {
        vl::Log::notify(appletInfo());

        mSceneKdTree = new vl::SceneManagerActorKdTree;
        rendering()->as<vl::Rendering>()->sceneManagers()->push_back(mSceneKdTree.get());

        mText = new vl::Text;
        mText->setFont( vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 10, false) );
        mText->setAlignment(vl::AlignHCenter | vl::AlignTop);
        mText->setViewportAlignment(vl::AlignHCenter | vl::AlignTop);
        mText->setColor(vl::white);
        mText->translate(0,-10,0);
        mTextActor = sceneManager()->tree()->addActor(mText.get(), new vl::Effect);
        mTextActor->effect()->shader()->enable(vl::EN_BLEND);

        mTestNumber = 0;
        mViewDepth  = -1;

        createScene();
        mText->setText( mText->text() + "\nPress left/right to change the test number\nPress up/down to change the visible tree level");
    }
  void initEvent()
  {
    vl::Log::notify(appletInfo());

    vl::ref<vl::Effect> effect = new vl::Effect;
    effect->shader()->enable(vl::EN_BLEND);

    const wchar_t* cprog =
      L"#include <stdio.h>\n"
      L"int main(int argc, char* argv[])\n"
      L"{\n"
      L"  printf(\"Hello Visualization Library!\");\n"
      L"  return 0;\n"
      L"}";

    const wchar_t* raven1 =
      L"Once upon a midnight dreary, while I pondered weak and weary,\n"
      L"Over many a quaint and curious volume of forgotten lore,\n"
      L"While I nodded, nearly napping, suddenly there came a tapping,\n"
      L"As of some one gently rapping, rapping at my chamber door.\n"
      L"'Tis some visitor,' I muttered, 'tapping at my chamber door -\n"
      L"Only this, and nothing more.'";

    const wchar_t* raven2 =
      L"Ah, distinctly I remember it was in the bleak December,\n"
      L"And each separate dying ember wrought its ghost upon the floor.\n"
      L"Eagerly I wished the morrow; - vainly I had sought to borrow\n"
      L"From my books surcease of sorrow - sorrow for the lost Lenore -\n"
      L"For the rare and radiant maiden whom the angels named Lenore -\n"
      L"Nameless here for evermore.";

    const wchar_t* raven3 =
      L"And the silken sad uncertain rustling of each purple curtain\n"
      L"Thrilled me - filled me with fantastic terrors never felt before;\n"
      L"So that now, to still the beating of my heart, I stood repeating\n"
      L"'Tis some visitor entreating entrance at my chamber door -\n"
      L"Some late visitor entreating entrance at my chamber door; -\n"
      L"This it is, and nothing more,'";

    const wchar_t* raven4 =
      L"Presently my soul grew stronger; hesitating then no longer,\n"
      L"'Sir,' said I, 'or Madam, truly your forgiveness I implore;\n"
      L"But the fact is I was napping, and so gently you came rapping,\n"
      L"And so faintly you came tapping, tapping at my chamber door,\n"
      L"That I scarce was sure I heard you' - here I opened wide the door; -\n"
      L"Darkness there, and nothing more.";

    vl::ref<vl::Font> font;
    if (mTestNumber == 0)
    {
      rendering()->as<vl::Rendering>()->camera()->viewport()->setClearColor( vl::white );

      font = vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 30);

      vl::ref<vl::Text> text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setKerningEnabled(false);
      text->setText( L"The Raven");
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignJustify );
      text->setAlignment( vl::AlignHCenter | vl::AlignTop );
      text->setViewportAlignment( vl::AlignHCenter | vl::AlignTop );
      text->setColor( vl::red );
      text->setShadowVector( vl::fvec2(5,5) );
      text->setOutlineEnabled(true);
      text->setOutlineColor(vl::black);
      text->translate(0,-20,0);

      float h = (float)text->boundingRectTransformed( rendering()->as<vl::Rendering>()->camera() ).minCorner().y();

      font = vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 10);
      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setText( L"By Egar Allan Poe");
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignJustify );
      text->setAlignment( vl::AlignHCenter | vl::AlignTop );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor( vl::black );
      text->setShadowVector( vl::fvec2(5,5) );
      text->translate(0,h-10,0);

      h = (float)text->boundingRectTransformed( rendering()->as<vl::Rendering>()->camera() ).minCorner().y();

      font = vl::defFontManager()->acquireFont("/font/bitstream-vera/Vera.ttf", 8);
      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setText( raven1 );
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignLeft );
      text->setAlignment( vl::AlignHCenter | vl::AlignTop );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter);
      text->setColor(vl::crimson);
      text->setBorderColor( vl::red );
      text->setShadowColor(vl::fvec4(0,0,0,0.3f));
      text->setBorderEnabled(true);
      text->translate(0,h-10,0);

      h = (float)text->boundingRectTransformed( rendering()->as<vl::Rendering>()->camera() ).minCorner().y();

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setText( raven2 );
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignCenter );
      text->setAlignment( vl::AlignHCenter | vl::AlignTop );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter);
      text->setColor(vl::crimson);
      text->setShadowColor(vl::fvec4(0,0,0,0.3f));
      text->setBorderEnabled(true);
      text->setBorderColor( vl::red );
      text->translate(0,h-20,0);

      h = (float)text->boundingRectTransformed( rendering()->as<vl::Rendering>()->camera() ).minCorner().y();

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setText( raven3 );
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignRight );
      text->setAlignment( vl::AlignHCenter | vl::AlignTop );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter);
      text->setColor(vl::crimson);
      text->setShadowColor(vl::fvec4(0,0,0,0.3f));
      text->setBorderEnabled(true);
      text->setBorderColor( vl::red );
      text->translate(0,h-20,0);

      h = (float)text->boundingRectTransformed( rendering()->as<vl::Rendering>()->camera() ).minCorner().y();

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setText( raven4 );
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignJustify );
      text->setAlignment( vl::AlignHCenter | vl::AlignTop );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter);
      text->setColor(vl::crimson);
      text->setShadowColor(vl::fvec4(0,0,0,0.3f));
      text->setBorderEnabled(true);
      text->setBorderColor( vl::red );
      text->translate(0,h-20,0);
    }
    else
    if (mTestNumber == 1)
    {
      font = vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 8);
      vl::ref<vl::Text> text;

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setKerningEnabled(false);
      text->setText( L"vl::AlignTop | vl::AlignLeft");
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignJustify );
      text->setAlignment( vl::AlignTop | vl::AlignLeft );
      text->setViewportAlignment( vl::AlignTop | vl::AlignLeft );
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setColor( vl::black );

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setKerningEnabled(false);
      text->setText( L"vl::AlignTop | vl::AlignRight");
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignJustify );
      text->setAlignment( vl::AlignTop | vl::AlignRight );
      text->setViewportAlignment( vl::AlignTop | vl::AlignRight );
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setColor( vl::black );

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setKerningEnabled(false);
      text->setText( L"vl::AlignBottom | vl::AlignLeft");
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignJustify );
      text->setAlignment( vl::AlignBottom | vl::AlignLeft );
      text->setViewportAlignment( vl::AlignBottom | vl::AlignLeft );
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setColor( vl::black );

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setKerningEnabled(false);
      text->setText( L"vl::AlignBottom | vl::AlignRight");
      text->setMode(vl::Text2D);
      text->setTextAlignment( vl::TextAlignJustify );
      text->setAlignment( vl::AlignBottom | vl::AlignRight );
      text->setViewportAlignment( vl::AlignBottom | vl::AlignRight );
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setColor( vl::black );

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont(font.get());
      text->setKerningEnabled(false);
      text->setText( L"vl::AlignVCenter | vl::AlignHCenter");
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignVCenter | vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignVCenter | vl::AlignHCenter );
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setColor( vl::black );
    }
    else
    if (mTestNumber == 2)
    {
      _text1 = new vl::Text;
      sceneManager()->tree()->addActor( _text1.get(), effect.get() );
      font = vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 10);
      _text1->setFont( font.get() );
      _text1->setText( cprog );
      _text1->setMode(vl::Text2D);
      _text1->setAlignment( vl::AlignVCenter | vl::AlignHCenter );
      _text1->setViewportAlignment( vl::AlignVCenter | vl::AlignHCenter );
      _text1->setColor(vl::black);
      _text1->setMargin(10);
      _text1->setBorderEnabled(true);
      _text1->setBackgroundEnabled(true);
      /* rotated _text1 needs smoothing to be properly rendern */
      _text1->font()->setSmooth(true);
    }
    else
    if (mTestNumber == 3)
    {
      vl::ref<vl::Text> text;

      float space = 75;

      vl::String system_font_directory = get_system_font_directory();

      /* chinese & japanese fonts */
      vl::ref<vl::Font> chinese_font = vl::defFontManager()->acquireFont(system_font_directory+"/simhei.ttf", 16);
      /* english, russian, hebrew, arabic */
      font = vl::defFontManager()->acquireFont(system_font_directory+"/arial.ttf", 16);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( vl::String::loadText("/text/greetings-en.txt") );
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(10);
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setShadowEnabled(true);
      text->setShadowColor( vl::fvec4(0,0,0,0.25f) );
      text->translate(0,-40-space*0,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( vl::String::loadText("/text/greetings-ru.txt") );
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(10);
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->translate(0,-40-space*1,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( vl::String::loadText("/text/greetings-he.txt") );
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(10);
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setLayout(vl::RightToLeftText);
      text->translate(0,-40-space*2,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( vl::String::loadText("/text/greetings-ar.txt") );
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(10);
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setLayout(vl::RightToLeftText);
      text->translate(0,-40-space*3,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( chinese_font.get() );
      text->setText( vl::String::loadText("/text/greetings-jp.txt") );
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(10);
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->translate(0,-40-space*4,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( chinese_font.get() );
      text->setText( vl::String::loadText("/text/greetings-ch.txt") );
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(10);
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->translate(0,-40-space*5,0);

      font = vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 8);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( L"English");
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignBottom| vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(0);
      text->translate(0,-40-space*0,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( L"Russian");
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignBottom| vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(0);
      text->translate(0,-40-space*1,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( L"Hebrew");
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignBottom| vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(0);
      text->translate(0,-40-space*2,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( L"Arabic");
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignBottom| vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(0);
      text->translate(0,-40-space*3,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( L"Japanese");
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignBottom| vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(0);
      text->translate(0,-40-space*4,0);

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), effect.get() );
      text->setFont( font.get() );
      text->setText( L"Chinese");
      text->setMode(vl::Text2D);
      text->setAlignment( vl::AlignBottom| vl::AlignHCenter );
      text->setViewportAlignment( vl::AlignTop | vl::AlignHCenter );
      text->setColor(vl::black);
      text->setMargin(0);
      text->translate(0,-40-space*5,0);
    }
    else
    if (mTestNumber == 4)
    {
      vl::ref<vl::Light> light = new vl::Light;

      vl::ref<vl::Geometry> planet = vl::makeIcosphere(vl::vec3(0,0,0), 1, 2 );
      planet->computeNormals();

      vl::ref<vl::Geometry> moon = vl::makeIcosphere(vl::vec3(0,0,0), 0.5, 1 );
      moon->computeNormals();

      vl::ref<vl::Effect> sun_effect = new vl::Effect;
      sun_effect->shader()->setRenderState( light.get(), 0 );
      sun_effect->shader()->enable(vl::EN_LIGHTING);
      sun_effect->shader()->enable(vl::EN_DEPTH_TEST);
      sun_effect->shader()->enable(vl::EN_CULL_FACE);
      sun_effect->shader()->gocMaterial()->setDiffuse(vl::gold);

      vl::ref<vl::Effect> planet_effect = new vl::Effect;
      planet_effect->shader()->setRenderState( light.get(), 0 );
      planet_effect->shader()->enable(vl::EN_LIGHTING);
      planet_effect->shader()->enable(vl::EN_DEPTH_TEST);
      planet_effect->shader()->enable(vl::EN_CULL_FACE);
      planet_effect->shader()->gocMaterial()->setDiffuse(vl::gray);

      vl::ref<vl::Effect> earth_effect = new vl::Effect;
      earth_effect->shader()->setRenderState( light.get(), 0 );
      earth_effect->shader()->enable(vl::EN_LIGHTING);
      earth_effect->shader()->enable(vl::EN_DEPTH_TEST);
      earth_effect->shader()->enable(vl::EN_CULL_FACE);
      earth_effect->shader()->gocMaterial()->setDiffuse(vl::royalblue);

      vl::ref<vl::Font> font = vl::defFontManager()->acquireFont("/font/bitstream-vera/Vera.ttf", 10);

      vl::ref<vl::Effect> name_effect = new vl::Effect;
      name_effect->shader()->setRenderState( light.get(), 0 );
      name_effect->shader()->enable(vl::EN_LIGHTING);
      name_effect->shader()->enable(vl::EN_DEPTH_TEST);
      name_effect->shader()->enable(vl::EN_CULL_FACE);
      name_effect->shader()->disable(vl::EN_LIGHTING);
      name_effect->shader()->enable(vl::EN_BLEND);
      ///* to avoid clipping artefacts due to partial character overlapping we either disable depth
      //   testing, set depth-write mask to false or enable an appropriate alpha testing. */
      // name_effect->shader()->disable(vl::EN_DEPTH_TEST);
      name_effect->shader()->enable(vl::EN_DEPTH_TEST);

      /* sun */

      sceneManager()->tree()->addActor( planet.get(), sun_effect.get() );
      vl::ref< vl::Text > text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), name_effect.get(), new vl::Transform );
      text->setFont(font.get());
      text->setMode( vl::Text2D );
      text->setText( L"Sun");
      text->setColor(vl::white);
      text->setAlignment(vl::AlignBottom|vl::AlignLeft);

      /* belts & planets */

      vl::ref<vl::Effect> belt_effect = new vl::Effect;
      belt_effect->shader()->setRenderState( light.get(), 0 );
      belt_effect->shader()->enable(vl::EN_LIGHTING);
      belt_effect->shader()->enable(vl::EN_DEPTH_TEST);
      belt_effect->shader()->enable(vl::EN_CULL_FACE);
      belt_effect->shader()->gocMaterial()->setFlatColor(vl::red);
      belt_effect->shader()->enable(vl::EN_BLEND);
      belt_effect->shader()->enable(vl::EN_LINE_SMOOTH);
      // render this first
      belt_effect->setRenderRank(-1);

      /* planet names */

      const wchar_t* names[] = {
        L"Mercury",
        L"Venus",
        L"Earth",
        L"Mars",
        L"Jupiter",
        L"Saturn",
        L"Uranus",
        L"Neptune",
        L"Pluto"
      };

      vl::ref<vl::Transform> belt_tr = new vl::Transform;
      rendering()->as<vl::Rendering>()->transform()->addChild( belt_tr.get() );

      for(int i=0; i<9; i++)
      {
        vl::ref< vl::Geometry > belt1 = vl::makeCircle(vl::vec3(0,0,0), 3.0f*(i+1));
        sceneManager()->tree()->addActor( belt1.get(), belt_effect.get(), belt_tr.get() );

        planet_tr[i] = new vl::Transform;
        rendering()->as<vl::Rendering>()->transform()->addChild( planet_tr[i].get() );

        if (i == 2)
          /* Earth */
          sceneManager()->tree()->addActor( planet.get(), earth_effect.get(), planet_tr[i].get() );
        else
          /* other planets */
          sceneManager()->tree()->addActor( planet.get(), planet_effect.get(), planet_tr[i].get() );

        vl::ref< vl::Text > text = new vl::Text;
        sceneManager()->tree()->addActor( text.get(), name_effect.get(), planet_tr[i].get() );
        text->setFont(font.get());
        text->setMode( vl::Text2D );
        text->setText( names[i] );
        text->setColor(vl::white);
        text->setAlignment(vl::AlignBottom | vl::AlignLeft);
        /* when the label follows an object the settings for text->setViewportAlignment don't have any effect */
      }

      /* moon */

      /* we want the Moon to rotate around the Earth so we make it's transform a child of the Earth's transform */

      moon_tr = new vl::Transform;
      planet_tr[2]->addChild(moon_tr.get());
      sceneManager()->tree()->addActor( moon.get(), planet_effect.get(), moon_tr.get() );

      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), name_effect.get(), moon_tr.get() );
      text->setFont(font.get());
      text->setMode( vl::Text2D );
      text->setText( L"Moon");
      text->setColor(vl::gold);
      text->setBorderColor(vl::royalblue);
      text->setBorderEnabled(true);
      text->setBackgroundEnabled(true);
      text->setBackgroundColor( vl::fvec4(1,1,1,0.35f) );
      text->setAlignment( vl::AlignVCenter | vl::AlignLeft );
      /* note: matrix transformations still apply in pixel coordinates and are often
         useful to offset the label from the followed object. */
      text->translate(5,0,0);

      /* the title */

      font = vl::defFontManager()->acquireFont("/font/bitstream-vera/Vera.ttf", 20);
      text = new vl::Text;
      sceneManager()->tree()->addActor( text.get(), name_effect.get() );
      text->setFont(font.get());
      text->setMode( vl::Text2D );
      text->setText( L"The Solar System");
      text->setColor(vl::white);
      text->setAlignment(vl::AlignTop | vl::AlignHCenter );
      text->setViewportAlignment(vl::AlignTop | vl::AlignHCenter );
      text->translate(0,-20,0);
    }
  }
  virtual void initEvent()
  {
    if ( !vl::canLoad("png") || !vl::canLoad("jpg") || !vl::canLoad("tga") || !vl::canLoad("tif") )
    {
      vl::Log::error("App_ImageFunctions test requires the following modules: VL_IO_2D_JPG, VL_IO_2D_PNG, VL_IO_2D_TIFF and VL_IO_2D_TGA.\n");
      vl::Time::sleep(2000);
      exit(1);
    }

    vl::Log::notify(appletInfo());

    bool use_mipmaps = true;

    vl::ref<vl::Image> img1 = vl::loadImage("/images/holebox.tif");
    // make sure it's in the right format
    img1 = img1->convertFormat(vl::IF_RGBA)->convertType(vl::IT_UNSIGNED_BYTE);
    vl::ref<vl::Image> img2;

    // check load/save routines
    vl::ref<vl::Image> img_a;
    vl::ref<vl::Image> img_b;
    vl::ref<vl::Image> img_c;
    vl::ref<vl::Image> img_d;

    vl::LoadWriterJPG* jpg_load_writer = vl::defLoadWriterManager()->loadWriter<vl::LoadWriterJPG>();
    if (jpg_load_writer)
    {
      jpg_load_writer->setQuality(90);
      vl::saveImage(img1.get(), "img_a.jpg");
      img_a = vl::loadImage("img_a.jpg");
    }

    vl::LoadWriterPNG* png_load_writer = vl::defLoadWriterManager()->loadWriter<vl::LoadWriterPNG>();
    if (png_load_writer)
    {
      png_load_writer->setCompression(9);
      vl::saveImage(img1.get(), "img_b.png");
      img_b = vl::loadImage("img_b.png");
    }

    vl::saveImage(img1.get(), "img_c.tga");
    img_c = vl::loadImage("img_c.tga");

    vl::saveImage(img1.get(), "img_d.tif");
    img_d = vl::loadImage("img_d.tif");

    VL_CHECK(img_a)
    VL_CHECK(img_b)
    VL_CHECK(img_c)
    VL_CHECK(img_d)

    // test image nearest sampling IF_RGBA/IT_UNSIGNED_BYTE
    vl::ref<vl::Image> img_x = new vl::Image;
    // copy image
    *img_x = *img1;
    // set it to black
    memset(img_x->pixels(), 0, img_x->requiredMemory());
    for(int x=0; x<img_x->width(); ++x)
    {
      for(int y=0; y<img_x->height(); ++y)
      {
        vl::fvec4 color = img1->sample(x,y);
        unsigned char* pixel = img_x->pixels() + img_x->pitch()*y + x*4;
        pixel[0] = (unsigned char)(color.r() * 255.0);
        pixel[1] = (unsigned char)(color.g() * 255.0);
        pixel[2] = (unsigned char)(color.b() * 255.0);
        pixel[3] = (unsigned char)(color.a() * 255.0);
      }
    }
    // test image linear sampling IF_RGBA/IT_UNSIGNED_BYTE
    vl::ref<vl::Image> img_y = new vl::Image;
    // copy image

    *img_y = *img1;
    // set it to black
    memset(img_y->pixels(), 0, img_y->requiredMemory());
    for(int x=0; x<img_y->width(); ++x)
    {
      for(int y=0; y<img_y->height(); ++y)
      {
        vl::fvec4 color = img1->sampleLinear((float)x,(float)y);
        unsigned char* pixel = img_y->pixels() + img_y->pitch()*y + x*4;
        pixel[0] = (unsigned char)(color.r() * 255.0);
        pixel[1] = (unsigned char)(color.g() * 255.0);
        pixel[2] = (unsigned char)(color.b() * 255.0);
        pixel[3] = (unsigned char)(color.a() * 255.0);
      }
    }

    // check image type conversion
    #if 1
      img2 = img1
      ->convertType(vl::IT_FLOAT)
      ->convertType(vl::IT_SHORT)
      ->convertType(vl::IT_INT)
      ->convertType(vl::IT_BYTE)
      ->convertType(vl::IT_UNSIGNED_BYTE)
      ->convertType(vl::IT_UNSIGNED_SHORT)
      ->convertType(vl::IT_UNSIGNED_INT)
     ;
    #endif

    // check image format conversion
    #if 1
      img2 = img1
        ->convertFormat(vl::IF_LUMINANCE_ALPHA)
        ->convertFormat(vl::IF_BGRA)
        ->convertFormat(vl::IF_RGBA)
        ->convertFormat(vl::IF_LUMINANCE_ALPHA)
     ;
    #endif

    // test image nearest sampling IF_LUMINANCE_ALPHA/IT_UNSIGNED_INT
    vl::ref<vl::Image> img_z = new vl::Image;
    // copy image
    *img_z = *img2;
    // set it to black
    memset(img_z->pixels(), 0, img_z->requiredMemory());
    for(int x=0; x<img_z->width(); ++x)
    {
      for(int y=0; y<img_z->height(); ++y)
      {
        vl::fvec4 color = img2->sample(x,y);
        unsigned char* pixel = img_z->pixels() + img_z->pitch()*y + x*2;
        pixel[0] = (unsigned char)(color.r() * 255.0);
        pixel[1] = (unsigned char)(color.a() * 255.0);
      }
    }

    // test image linear sampling IF_LUMINANCE_ALPHA/IT_UNSIGNED_INT
    vl::ref<vl::Image> img_w = new vl::Image;
    // copy image
    *img_w = *img2;
    // set it to black
    memset(img_w->pixels(), 0, img_w->requiredMemory());
    for(int x=0; x<img_w->width(); ++x)
    {
      for(int y=0; y<img_w->height(); ++y)
      {
        vl::fvec4 color = img2->sampleLinear((float)x,(float)y);
        unsigned char* pixel = img_w->pixels() + img_w->pitch()*y + x*2;
        pixel[0] = (unsigned char)(color.r() * 255.0);
        pixel[1] = (unsigned char)(color.a() * 255.0);
      }
    }

    vl::ref<vl::Geometry> quad = vl::makeGrid( vl::vec3(0,0,0), 10, 10, 2, 2, true, vl::fvec2(0,0), vl::fvec2(1,1) );
    quad->transform( vl::mat4::getRotation(-90, 1,0,0), false );

    // (1)
    // transform
    vl::ref<vl::Transform> tr_1 = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_1.get());
    tr_1->setLocalMatrix(vl::mat4::getTranslation(-5,0,0));
    // effect
    vl::ref<vl::Effect> fx_1 = new vl::Effect;
    fx_1->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_1 = new vl::Texture( img1.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_1->shader()->gocTextureSampler(0)->setTexture( texture_1.get() );
    fx_1->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_1->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_1.get(), tr_1.get() );

    // (2)
    // transform
    vl::ref<vl::Transform> tr_2 = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_2.get());
    tr_2->setLocalMatrix(vl::mat4::getTranslation(+5,0,0));
    // effect
    vl::ref<vl::Effect> fx_2 = new vl::Effect;
    fx_2->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_2 = new vl::Texture( img2.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_2->shader()->gocTextureSampler(0)->setTexture( texture_2.get() );
    fx_2->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_2->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_2.get(), tr_2.get() );

    // (x)
    // transform
    vl::ref<vl::Transform> tr_x = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_x.get());
    tr_x->setLocalMatrix(vl::mat4::getTranslation(-2.5-5,+7.5,0) * vl::mat4::getScaling(0.5f,0.5f,1.0f));
    // effect
    vl::ref<vl::Effect> fx_x = new vl::Effect;
    fx_x->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_x = new vl::Texture( img_x.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_x->shader()->gocTextureSampler(0)->setTexture( texture_x.get() );
    fx_x->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_x->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_x.get(), tr_x.get() );

    // (y)
    // transform
    vl::ref<vl::Transform> tr_y = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_y.get());
    tr_y->setLocalMatrix(vl::mat4::getTranslation(-2.5,+7.5,0) * vl::mat4::getScaling(0.5f,0.5f,1.0f));
    // effect
    vl::ref<vl::Effect> fx_y = new vl::Effect;
    fx_y->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_y = new vl::Texture( img_y.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_y->shader()->gocTextureSampler(0)->setTexture( texture_y.get() );
    fx_y->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_y->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_y.get(), tr_y.get() );

    // (z)
    // transform
    vl::ref<vl::Transform> tr_z = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_z.get());
    tr_z->setLocalMatrix(vl::mat4::getTranslation(+2.5,+7.5,0) * vl::mat4::getScaling(0.5f,0.5f,1.0f));
    // effect
    vl::ref<vl::Effect> fx_z = new vl::Effect;
    fx_z->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_z = new vl::Texture( img_z.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_z->shader()->gocTextureSampler(0)->setTexture( texture_z.get() );
    fx_z->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_z->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_z.get(), tr_z.get() );

    // (w)
    // transform
    vl::ref<vl::Transform> tr_w = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_w.get());
    tr_w->setLocalMatrix(vl::mat4::getTranslation(+2.5+5.0,+7.5,0) * vl::mat4::getScaling(0.5f,0.5f,1.0f));
    // effect
    vl::ref<vl::Effect> fx_w = new vl::Effect;
    fx_w->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_w = new vl::Texture( img_w.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_w->shader()->gocTextureSampler(0)->setTexture( texture_w.get() );
    fx_w->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_w->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_w.get(), tr_w.get() );

    // (a)
    // transform
    vl::ref<vl::Transform> tr_a = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_a.get());
    tr_a->setLocalMatrix(vl::mat4::getTranslation(-2.5-5,-7.5,0) * vl::mat4::getScaling(0.5f,0.5f,1.0f));
    // effect
    vl::ref<vl::Effect> fx_a = new vl::Effect;
    fx_a->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_a = new vl::Texture( img_a.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_a->shader()->gocTextureSampler(0)->setTexture( texture_a.get() );
    fx_a->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_a->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_a.get(), tr_a.get() );

    // (b)
    // transform
    vl::ref<vl::Transform> tr_b = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_b.get());
    tr_b->setLocalMatrix(vl::mat4::getTranslation(-2.5,-7.5,0) * vl::mat4::getScaling(0.5f,0.5f,1.0f));
    // effect
    vl::ref<vl::Effect> fx_b = new vl::Effect;
    fx_b->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_b = new vl::Texture( img_b.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_b->shader()->gocTextureSampler(0)->setTexture( texture_b.get() );
    fx_b->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_b->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_b.get(), tr_b.get() );

    // (c)
    // transform
    vl::ref<vl::Transform> tr_c = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_c.get());
    tr_c->setLocalMatrix(vl::mat4::getTranslation(+2.5,-7.5,0) * vl::mat4::getScaling(0.5f,0.5f,1.0f));
    // effect
    vl::ref<vl::Effect> fx_c = new vl::Effect;
    fx_c->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_c = new vl::Texture( img_c.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_c->shader()->gocTextureSampler(0)->setTexture( texture_c.get() );
    fx_c->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_c->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_c.get(), tr_c.get() );

    // (d)
    // transform
    vl::ref<vl::Transform> tr_d = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(tr_d.get());
    tr_d->setLocalMatrix(vl::mat4::getTranslation(+2.5+5,-7.5,0) * vl::mat4::getScaling(0.5f,0.5f,1.0f));
    // effect
    vl::ref<vl::Effect> fx_d = new vl::Effect;
    fx_d->shader()->enable(vl::EN_BLEND);
    // setup texture
    vl::ref<vl::Texture> texture_d = new vl::Texture( img_d.get(), vl::TF_RGBA, use_mipmaps, false );
    fx_d->shader()->gocTextureSampler(0)->setTexture( texture_d.get() );
    fx_d->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    fx_d->shader()->gocTextureSampler(0)->texture()->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);
    // add actor
    sceneManager()->tree()->addActor( quad.get(), fx_d.get(), tr_d.get() );
  }
  void initEvent()
  {
    vl::Log::print(appletInfo());

    mMode = NoMode;

    openglContext()->setContinuousUpdate(false);

    // camera setup
    rendering()->as<vl::Rendering>()->setNearFarClippingPlanesOptimized(false);
    rendering()->as<vl::Rendering>()->camera()->setProjectionAsOrtho2D();
    rendering()->as<vl::Rendering>()->camera()->setViewMatrix( vl::mat4() );

    // disable trackball and ghost camera manipulator
    trackball()->setEnabled(false);
    ghostCameraManipulator()->setEnabled(false);

    // dummy empty image
    mImage = new vl::Image(8,8,0, 1, vl::IF_RGBA, vl::IT_UNSIGNED_BYTE);
    memset(mImage->pixels(), 0xFF, mImage->requiredMemory());

    // texture setup
    mTexture = new vl::Texture;
    mTexture->getTexParameter()->setWrapS(vl::TPW_CLAMP);
    mTexture->getTexParameter()->setWrapT(vl::TPW_CLAMP);
    mTexture->getTexParameter()->setMinFilter(vl::TPF_LINEAR);
    mTexture->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    mTexture->prepareTexture2D(mImage.get(), vl::TF_RGBA);
    mTextureMatrix = new vl::TextureMatrix(0);

    vl::ref<vl::Effect> image_fx = new vl::Effect;
    image_fx->shader()->gocTextureUnit(0)->setTexture(mTexture.get());
    image_fx->shader()->setRenderState( mTextureMatrix.get() );
    image_fx->shader()->enable(vl::EN_BLEND);

    mGrid = vl::makeGrid( vl::vec3(0,0,0), 1.0f, 1.0f, mSlices, mSlices, true, vl::fvec2(0,0), vl::fvec2(1,1) );
    mGrid->setVBOEnabled(false);
    mGrid->transform(vl::mat4::getRotation(-90,1,0,0));
    mPoints = dynamic_cast<vl::ArrayFloat3*>(mGrid->vertexArray());

    // save point coordinates for the animation keyframe
    mPointsRest = new vl::ArrayFloat3;
    mPointsRest->resize( mPoints->size() );
    memcpy(mPointsRest->ptr(), mPoints->ptr(), mPoints->bytesUsed());
    // animate points buffer
    mPointsAnim = new vl::ArrayFloat3;
    mPointsAnim->resize( mPoints->size() );

    mTransform = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(mTransform.get());
    sceneManager()->tree()->addActor(mGrid.get(), image_fx.get(), mTransform.get());

    mCursorTransform = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(mCursorTransform.get());
    mBrushSize = 100;
    vl::ref<vl::Effect> cursor_fx = new vl::Effect;
    cursor_fx->shader()->gocLogicOp()->set(vl::LO_INVERT);
    cursor_fx->shader()->enable(vl::EN_COLOR_LOGIC_OP);
    vl::ref<vl::Geometry> cursor = vl::makeCircle(vl::vec3(0,0,0), 1.0f);
    
    cursor->transform(vl::mat4::getRotation(-90,1,0,0));
    mCursorActor = sceneManager()->tree()->addActor(cursor.get(), cursor_fx.get(), mCursorTransform.get());
    // ensure the cursor is rendered over the image (whose render rank is 0 by default)
    mCursorActor->setRenderRank(1);

    mText = new vl::Text;
    mText->setFont( vl::defFontManager()->acquireFont("/font/bitstream-vera/Vera.ttf", 10) );
    mText->translate(0,-5,0);
    mText->setColor(vl::white);
    mText->setBackgroundColor(vl::fvec4(0,0,0,.75f));
    mText->setBackgroundEnabled(true);
    mHelpOn = true;
    updateText();

    vl::ref<vl::Effect> txt_fx = new vl::Effect;
    txt_fx->shader()->enable(vl::EN_BLEND);
    vl::Actor* txt_act = sceneManager()->tree()->addActor(mText.get(), txt_fx.get());
    // draw the text for last
    txt_act->setRenderRank(2);

    loadFile("/images/toy.jpg");
  }
  void initEvent()
  {
    vl::Log::notify(appletInfo());

    if(!vl::Has_GL_Version_4_0)
    {
      vl::Log::error("This test requires OpenGL 4!\n");
      vl::Time::sleep(2000);
      exit(1);
    }

    const int   patch_count      = 128;
    const float world_size       = 2500.0;
    const float height_scale     = 150.0;
    const float pixel_per_edge   = 16.0f;
    const float max_tessellation = 64.0f;

    vl::ref< vl::Geometry > geom_patch = makeGrid( vl::vec3(), world_size, world_size, patch_count, patch_count, false );

    geom_patch->convertToVertexAttribs();

    // patch parameter associated to the draw call
    vl::ref<vl::PatchParameter> patch_param = new vl::PatchParameter;
    patch_param->setPatchVertices(4);
    geom_patch->drawCalls()->at(0)->setPatchParameter( patch_param.get() );
    geom_patch->drawCalls()->at(0)->setPrimitiveType(vl::PT_PATCHES);

    vl::ref<vl::Texture> hmap = new vl::Texture("/images/ps_height_4k.jpg", vl::TF_RED, false, false);
    vl::ref<vl::Texture> tmap = new vl::Texture("/images/ps_texture_4k.jpg", vl::TF_RGBA, true, false);

    hmap->getTexParameter()->setMinFilter(vl::TPF_LINEAR);
    hmap->getTexParameter()->setMagFilter(vl::TPF_LINEAR);

    // tessellated patches fx
    vl::ref<vl::Effect> fx = new vl::Effect;
    fx->shader()->enable(vl::EN_DEPTH_TEST);
    fx->shader()->gocTextureSampler(0)->setTexture( hmap.get() );
    fx->shader()->gocTextureSampler(1)->setTexture( tmap.get() );

    // bind all the necessary stages to the GLSLProgram
    mGLSL = fx->shader()->gocGLSLProgram();
    mGLSL->attachShader( new vl::GLSLVertexShader("glsl/tess_grid.vs") );
    mGLSL->attachShader( new vl::GLSLTessControlShader("glsl/tess_grid.tcs") );
    mGLSL->attachShader( new vl::GLSLTessEvaluationShader("glsl/tess_grid.tes") );
    mGLSL->attachShader( new vl::GLSLFragmentShader("glsl/tess_grid.fs") );
    mGLSL->gocUniform("pixel_per_edge")->setUniformF(pixel_per_edge);
    mGLSL->gocUniform("max_tessellation")->setUniformF(max_tessellation);
    mGLSL->gocUniform("screen_size")->setUniform(vl::fvec2(512,512));
    mGLSL->gocUniform("world_size")->setUniformF(world_size);
    mGLSL->gocUniform("height_scale")->setUniformF(height_scale);
    mGLSL->gocUniform("tex_heghtmap")->setUniformI(0);
    mGLSL->gocUniform("tex_diffuse")->setUniformI(1);

    mGLSL->addAutoAttribLocation( 0, "vl_Position" );

    // tessellated patches fx_wire
    vl::ref<vl::Effect> fx_wire = new vl::Effect;
    fx_wire->shader()->enable(vl::EN_DEPTH_TEST);
    fx_wire->shader()->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE);
    fx_wire->shader()->gocTextureSampler(0)->setTexture( hmap.get() );
    fx_wire->shader()->gocPolygonOffset()->set(-1.0f, -1.0f);
    fx_wire->shader()->enable(vl::EN_POLYGON_OFFSET_LINE);

    // bind all the necessary stages to the GLSLProgram
    mGLSLWire = fx_wire->shader()->gocGLSLProgram();
    mGLSLWire->attachShader( new vl::GLSLVertexShader("glsl/tess_grid.vs") );
    mGLSLWire->attachShader( new vl::GLSLTessControlShader("glsl/tess_grid.tcs") );
    mGLSLWire->attachShader( new vl::GLSLTessEvaluationShader("glsl/tess_grid.tes") );
    mGLSLWire->attachShader( new vl::GLSLFragmentShader("glsl/tess_grid_wire.fs") );
    mGLSLWire->gocUniform("pixel_per_edge")->setUniformF(pixel_per_edge);
    mGLSLWire->gocUniform("max_tessellation")->setUniformF(max_tessellation);
    mGLSLWire->gocUniform("screen_size")->setUniform(vl::fvec2(512,512));
    mGLSLWire->gocUniform("world_size")->setUniformF(world_size);
    mGLSLWire->gocUniform("height_scale")->setUniformF(height_scale);
    mGLSLWire->gocUniform("tex_heghtmap")->setUniformI(0);
    mGLSLWire->gocUniform("wire_color")->setUniform(vl::lightgreen);

    mGLSLWire->addAutoAttribLocation( 0, "vl_Position" );

    sceneManager()->tree()->addActor( geom_patch.get(), fx.get(), NULL )->setRenderRank(0);
    
    mWireActor = sceneManager()->tree()->addActor( geom_patch.get(), fx_wire.get(), NULL );
    mWireActor->setRenderRank(1);

    // debugging
    #if 0
      // base patch grid
      vl::ref< vl::Geometry > geom_quads = makeGrid(vl::fvec3(), world_size,world_size, patch_count,patch_count, true);
      geom_quads->setColor(vl::red);
      // base patch grid fx
      vl::ref<vl::Effect> fx_grid = new vl::Effect;
      fx_grid->shader()->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE);
      // add grid
      sceneManager()->tree()->addActor( geom_quads.get(), fx_grid.get(), NULL )->setRenderRank(2);
    #endif
  }
  void initEvent()
  {
    vl::Log::notify(appletInfo());

    // hemisphere base geometry
    vl::ref< vl::Geometry > geom_patch = new vl::Geometry;

    // hemisphere base geometry vertices
    vl::ref<vl::ArrayFloat3 > verts = new vl::ArrayFloat3;
    verts->resize(12);

    verts->at(0)  = vl::fvec3(1,0,0);
    verts->at(1)  = vl::fvec3(0,1,0);
    verts->at(2)  = vl::fvec3(0,0,1);
    
    verts->at(3)  = vl::fvec3(1,0,0);
    verts->at(4)  = vl::fvec3(0,0,-1);
    verts->at(5)  = vl::fvec3(0,1,0);
    
    verts->at(6)  = vl::fvec3(0,0,-1);
    verts->at(7)  = vl::fvec3(-1,0,0);
    verts->at(8)  = vl::fvec3(0,1,0);
    
    verts->at(9)  = vl::fvec3(-1,0,0);
    verts->at(10) = vl::fvec3(0,0,1);
    verts->at(11) = vl::fvec3(0,1,0);
    
    // hemisphere base geometry vertex colors
    vl::ref<vl::ArrayFloat3 > cols = new vl::ArrayFloat3;
    cols->resize(12);

    cols->at(0)  = vl::fvec3(1,0,0);
    cols->at(1)  = vl::fvec3(1,0,0);
    cols->at(2)  = vl::fvec3(1,0,0);
    
    cols->at(3)  = vl::fvec3(0,1,0);
    cols->at(4)  = vl::fvec3(0,1,0);
    cols->at(5)  = vl::fvec3(0,1,0);
    
    cols->at(6)  = vl::fvec3(1,1,0);
    cols->at(7)  = vl::fvec3(1,1,0);
    cols->at(8)  = vl::fvec3(1,1,0);
    
    cols->at(9)  = vl::fvec3(0,0,1);
    cols->at(10) = vl::fvec3(0,0,1);
    cols->at(11) = vl::fvec3(0,0,1);
    
    // vertex array
    geom_patch->setVertexArray( verts.get() );

    // color array
    geom_patch->setColorArray( cols.get() );
    
    // draw call
    vl::ref< vl::DrawArrays> da = new vl::DrawArrays(vl::PT_PATCHES, 0, verts->size());
    geom_patch->drawCalls()->push_back(da.get());
    
    // patch parameter associated to the draw call
    vl::ref<vl::PatchParameter> patch_param = new vl::PatchParameter;
    patch_param->setPatchVertices(3);
    da->setPatchParameter( patch_param.get() );

    // effect: light + depth testing
    vl::ref<vl::Effect> fx = new vl::Effect;
    fx->shader()->enable(vl::EN_DEPTH_TEST);

    // bind all the necessary stages to the GLSLProgram
    mGLSL = fx->shader()->gocGLSLProgram();
    mGLSL->attachShader( new vl::GLSLVertexShader("glsl/smooth_triangle.vs") );
    mGLSL->attachShader( new vl::GLSLTessControlShader("glsl/smooth_triangle.tcs") );
    mGLSL->attachShader( new vl::GLSLTessEvaluationShader("glsl/smooth_triangle.tes") );
    mGLSL->attachShader( new vl::GLSLGeometryShader("glsl/smooth_triangle.gs") );
    mGLSL->gocUniform("Outer")->setUniformF(10.0f);
    mGLSL->gocUniform("Inner")->setUniformF(10.0f);
    mGLSL->gocUniform("Radius")->setUniformF(1.0f);

    sceneManager()->tree()->addActor( geom_patch.get(), fx.get(), NULL );
  }
  virtual void initEvent()
  {
    vl::Log::print(appletInfo());

    // disable trackball and ghost camera manipulator
    trackball()->setEnabled(false);
    ghostCameraManipulator()->setEnabled(false);

    // camera setup

    rendering()->as<vl::Rendering>()->setNearFarClippingPlanesOptimized(false);
    rendering()->as<vl::Rendering>()->camera()->setProjectionAsOrtho2D();
    // reset view matrix to I
    rendering()->as<vl::Rendering>()->camera()->setViewMatrix( vl::mat4() );

    // load images used later as textures
    
    // load colorful pattern & substitute black with transparent blue
    vl::ref<vl::Image> pattern  = vl::loadImage("/images/pattern.bmp");
    pattern->substituteColorRGB_RGBA(0x000000,0x0000FFAA);
    // load transparent star
    vl::ref<vl::Image> star = vl::loadImage("/images/star.png");
    // colorize the point to green and black
    vl::ref<vl::Image> circle16_bg = vl::loadImage("/images/circle16.png");
    circle16_bg->substituteColorGreenKey(0x00FF00,0x000000);
    // colorize the point to yellow and red
    vl::ref<vl::Image> circle16_yr = vl::loadImage("/images/circle16.png");
    circle16_yr->substituteColorGreenKey(0xFFFF00,0xFF0000);
    // generate the color spectrums
    vl::ref<vl::Image> spectrum1 = vl::makeColorSpectrum(128, vl::blue,  vl::green, vl::yellow, vl::red);
    vl::ref<vl::Image> spectrum2 = vl::makeColorSpectrum(128, vl::black, vl::white, vl::gray,   vl::black);

    // add a new VectorGraphics to our SceneManagerVectorGraphics
  
    vl::ref<vl::VectorGraphics> vg = new vl::VectorGraphics;
    vl::ref<vl::SceneManagerVectorGraphics> vgscene = new vl::SceneManagerVectorGraphics;
    vgscene->vectorGraphicObjects()->push_back(vg.get());
    rendering()->as<vl::Rendering>()->sceneManagers()->push_back(vgscene.get());

    // start drawing with our new VectorGraphics object!

    vg->startDrawing();

      // clear the viewport
      vg->clearColor(vl::white);

      // ###### textured quad rendering ######

      vg->setImage(pattern.get());
      // this way the texels are perfectly centered on the pixels
      vg->translate(-0.5f,-0.5f);

      vg->pushMatrix();
        // textured quad #1 repeat texturing
        vg->translate(10,110);
        vg->setTextureMode(vl::TextureMode_Repeat);
        vg->fillQuad( 0,0 , pattern->width()*3.0f,pattern->height()*3.0f );
        // textured quad #2 stretch texturing
        vg->translate(100,0);
        vg->setTextureMode(vl::TextureMode_Clamp);
        vg->fillQuad( 0,0 , pattern->width()*3.0f,pattern->height()*3.0f );
        // textured quad #3 stretch texturing
        vg->translate(100,0);
        vg->setImage(spectrum2.get());
        vg->setTextureMode(vl::TextureMode_Clamp);
        vg->fillQuad( 0,0 , pattern->width()*3.0f,pattern->height()*3.0f );
      vg->popMatrix();

      // ###### line rendering ###### 

      vg->setImage(NULL);
      vg->setLineWidth(1.0f);
      vg->setColor(vl::black);
      vg->resetMatrix();
      vg->translate(10,250);

      vg->setLineStipple(vl::LineStipple_Dash);
      vg->drawLine(0,0, 200,0);

      vg->translate(0,10);
      vg->setLineStipple(vl::LineStipple_Dash4);
      vg->drawLine(0,0, 200,0);

      vg->translate(0,10);
      vg->setLineStipple(vl::LineStipple_Dash8);
      vg->drawLine(0,0, 200,0);

      vg->translate(0,10);
      vg->setLineStipple(vl::LineStipple_DashDot);
      vg->drawLine(0,0, 200,0);

      vg->translate(0,10);
      vg->setLineStipple(vl::LineStipple_DashDotDot);
      vg->drawLine(0,0, 200,0);

      vg->translate(0,10);
      vg->setLineStipple(vl::LineStipple_Dot);
      vg->drawLine(0,0, 200,0);

      vg->translate(0,10);
      vg->setLineStipple(vl::LineStipple_Solid);
      vg->drawLine(0,0, 200,0);

      vg->resetMatrix();
      vg->translate(10,350);
      for(int x=0; x<=100; x+=4)
        vg->drawLine(x,0,x,100);
      for(int y=0; y<=100; y+=4)
        vg->drawLine(0,y,100,y);

      // ###### textured point rendering + scissor ###### 

      // with the Scissor we can clip the rendering against a specific rectangular area
      int scissor_w = 200;
      int scissor_h = 200;
      vg->setScissor(256-scissor_w/2,256+128-scissor_h/2,scissor_w,scissor_h);

      vg->setColor(vl::fvec4(1,1,1,0.5f)); // transparent white
      vg->setPoint(circle16_bg.get()); // the same as setImage(image) + setPointSize(image->width())
      vg->resetMatrix();
      vg->translate(256,256+128);
      // generate the points
      std::vector<vl::dvec2> points;
      for(int i=0; i<1000; ++i)
      {
        points.push_back(vl::dvec2(rand()%128-64,rand()%128-64));
        points[i].normalize();
        points[i] *= (rand()%1280) / 10.0f;
        // snap to integer coordinates to avoid aliasing problems
        points[i] = vl::trunc(points[i]);
      }
      // draw the points
      vg->drawPoints(points);

      vg->setPoint(circle16_yr.get()); // the same as setImage(image) + setPointSize(image->width())
      points.clear();
      for(int i=0; i<200; ++i)
      {
        points.push_back(vl::dvec2(rand()%128-64,rand()%128-64));
        points[i].normalize();
        points[i] *= (rand()%1280) / 10.0f;
        // snap to integer coordinates to avoid aliasing problems
        points[i] = vl::trunc(points[i]);
      }
      // draw the points
      vg->drawPoints(points);

      vg->removeScissor();

      // ###### rounded point rendering ###### 

      vg->setImage(NULL);
      vg->setPointSize(7);
      vg->setPointSmoothing(true); /* default value */
      vg->setColor(vl::crimson);
      vg->translate(196,64);
      points.clear();
      for(int i=0; i<100; ++i)
      {
        points.push_back(vl::dvec2(rand()%128-64,rand()%128-64));
        points[i].normalize();
        points[i] *= (rand()%640) / 10.0f;
        // snap to integer coordinates to avoid aliasing problems
        points[i] = vl::trunc(points[i]);
      }
      vg->drawPoints(points);

      // ###### squared point rendering ###### 

      vg->setImage(NULL);
      vg->setPointSize(5);
      vg->setPointSmoothing(false);
      vg->setColor(vl::green);
      vg->translate(0,-128);
      points.clear();
      for(int i=0; i<100; ++i)
      {
        points.push_back(vl::dvec2(rand()%128-64,rand()%128-64));
        points[i].normalize();
        points[i] *= (rand()%640) / 10.0f;
        // snap to integer coordinates to avoid aliasing problems
        points[i] = vl::trunc(points[i]);
      }
      vg->drawPoints(points);

      // ###### stencil buffer rendering ###### 

      // reset states
      vg->resetMatrix();
      vg->setColor(vl::white);
      vg->setImage(NULL);

      // clear the stencil buffer
      vg->clearStencil(0);
      // enable stencil test
      vg->setStencilTestEnabled(true);
      // setup stencil test: writes 0x01 on the stencil buffer when rendering polygons, lines etc.
      vg->setStencilFunc(vl::FU_NOTEQUAL, 0x01, 0x01);
      vg->setStencilOp(vl::SO_REPLACE, vl::SO_REPLACE, vl::SO_REPLACE);

      // ###### render the rose on the stencil buffer ###### 

      // rose create and bind transform
      mRoseTransform = new vl::Transform;
      rendering()->as<vl::Rendering>()->transform()->addChild(mRoseTransform.get());
      // draw our rotating rose as a set of 4 filled ellipses and bind them to mRoseTransform
      vg->fillEllipse(0,0 , 150,25)->setTransform(mRoseTransform.get());
      vg->pushMatrix();
      vg->rotate(45);
      vg->fillEllipse(0,0 , 150,25)->setTransform(mRoseTransform.get());
      vg->rotate(45);
      vg->fillEllipse(0,0 , 150,25)->setTransform(mRoseTransform.get());
      vg->rotate(45);
      vg->fillEllipse(0,0 , 150,25)->setTransform(mRoseTransform.get());
      vg->popMatrix();

      // ###### fill the rose with color ###### 

      // setup stencil test: renders only where the stencil buffer is set to 0x01
      vg->setStencilFunc(vl::FU_EQUAL, 0x01, 0x01);
      vg->setStencilOp(vl::SO_KEEP, vl::SO_KEEP, vl::SO_KEEP);

      // make sure our matrix is clean
      vg->resetMatrix();
      // render random blue ellipses
      vg->setColor(vl::blue);
      for(int i=0; i<400; ++i)
        vg->drawEllipse(rand()%512,rand()%512 , rand()%20+10,rand()%20+10);
      // renders concentric red circles
      vg->setColor(vl::red);
      for(int i=0; i<256/4; ++i)
        vg->drawEllipse(256,256 , i*8,i*8);

      // finish with the stencil
      vg->setStencilTestEnabled(false);

      // render text following our rotating rose
      vg->setFont("/font/bitstream-vera/Vera.ttf", 14, false);
      vg->setColor(vl::black);
      // note that the 2D text is not transformed by mRoseTransform but just follows an idea point transformed by mRoseTransform.
      vg->drawText("Stencil buffer in action here!", vl::AlignHCenter|vl::AlignVCenter)->setTransform(mRoseTransform.get());

      // ###### draws a rotated text ###### 

      vg->setColor(vl::black);
      vg->setFont("/font/bitstream-vera/VeraMono.ttf", 14, true);
      vg->pushMatrix();
      vg->rotate(45);
      vg->drawText(256, 256, "Rotated Text", vl::AlignHCenter|vl::AlignVCenter);
      vg->popMatrix();

      // ###### transparent star image ###### 

      vg->pushState();
        vg->setColor(vl::fvec4(1,1,1,0.75f)); // transparent white
        vg->setImage(star.get());
        vg->translate(-star->width()/2,-star->height()/2); // center the quad
        vl::Actor* rota_star = vg->fillQuad(0,0,star->width(),star->height());
        mStarTransform = new vl::Transform;
        rota_star->setTransform( mStarTransform.get() );
        rendering()->as<vl::Rendering>()->transform()->addChild( mStarTransform.get() );
      vg->popState();

      // ###### how to instance multiple times the same object ###### 

      // generate 5 corner star: line loop primitive
      std::vector<vl::dvec2> star_line_loop;
      for(int i=0; i<5; ++i)
      {
        vl::dvec3 v = vl::dmat4::getRotation(90.0+i*360.0/5.0*2.0 , 0,0,1) * vl::dvec3(50.0,0,0);
        // snap to integer coordinates to avoid aliasing
        v = vl::trunc(v);
        star_line_loop.push_back(v.xy());
      }

      // ###### generate 5 corner star: lines primitive ###### 
      std::vector<vl::dvec2> star_lines;
      for(int i=0; i<5; ++i)
      {
        vl::dvec3 v1 = vl::dmat4::getRotation(90.0+i*360.0/5.0*2.0 , 0,0,1) * vl::dvec3(50.0,0,0);
        vl::dvec3 v2 = vl::dmat4::getRotation(90.0+((i+1)%5)*360.0/5.0*2.0 , 0,0,1) * vl::dvec3(50.0,0,0);
        // snap to integer coordinates to avoid aliasing
        v1 = vl::trunc(v1);
        v2 = vl::trunc(v2);
        star_lines.push_back(v1.xy());
        star_lines.push_back(v2.xy());
      }

      // star1
      vg->setLineWidth(4.0f);
      vg->setColor(vl::gold);
      vl::Actor* star1 = vg->drawLineLoop(star_line_loop);
      // star2 - recycle the geometry from star1
      vg->setLineWidth(2.0f);
      vg->setColor(vl::red);
      vl::Actor* star2 = vg->drawActorCopy(star1);
      // star3 - recycle the geometry from star1
      vg->setLineWidth(1.0f);
      vg->setLineStipple(vl::LineStipple_DashDotDot);
      vl::Actor* star3 = vg->drawActorCopy(star1);
      // star4 - texturing #1
      vg->setColor(vl::white); // make sure color is white so that the texture color is not filtered
      vg->setImage(spectrum1.get());
      vg->setLineWidth(2.0f);
      vg->setLineStipple(vl::LineStipple_Solid);
      // Here we call drawLineLoop() because we need to create a new geometry instance
      // so that VL can generate appropriate UV texture coordinates that are dependent
      // on the currently active Image.
      vl::Actor* star4 = vg->drawLineLoop(star_line_loop);
      // star5 - texturing #2
      // Here we draw the star using drawLines() instead or drawLineLoop().
      // Note how drawLines() and drawLineLoop() generate different texturing effects.
      vl::Actor* star5 = vg->drawLines(star_lines);

      // render the 4 instances in 4 different points
      star1->setTransform( new vl::Transform );
      star2->setTransform( new vl::Transform );
      star3->setTransform( new vl::Transform );
      star4->setTransform( new vl::Transform );
      star5->setTransform( new vl::Transform );
      star1->transform()->setLocalMatrix( vl::mat4::getTranslation(50,50,0) );
      star2->transform()->setLocalMatrix( vl::mat4::getTranslation(150,50,0) );
      star3->transform()->setLocalMatrix( vl::mat4::getTranslation(250,50,0) );
      star4->transform()->setLocalMatrix( vl::mat4::getTranslation(350,50,0) );
      star5->transform()->setLocalMatrix( vl::mat4::getTranslation(450,50,0) );
      // Since they are not animated we can setup the matrices without binding it to the Rendering's root Transform
      star1->transform()->computeWorldMatrix();
      star2->transform()->computeWorldMatrix();
      star3->transform()->computeWorldMatrix();
      star4->transform()->computeWorldMatrix();
      star5->transform()->computeWorldMatrix();

    vg->endDrawing();
  }
  virtual void initEvent()
  {
    if (!vl::defLoadWriterManager()->canLoad("md2"))
    {
      vl::Log::error("App_MorphAnimation requires VL_IO_2D_MD2.\n");
      vl::Time::sleep(3000);
      exit(1);
    }

    vl::Log::print(appletInfo());

    const int actor_count = 1000;

    ghostCameraManipulator()->setMovementSpeed(500.0f);
    bool glsl_vertex_blend = GLEW_VERSION_2_0 ? true : false;
    const float area_unit  = 1500.0f*1500.0f/2000.0f;
    const float size = sqrt( actor_count * area_unit );

    // common effect settings

    vl::ref<vl::Light> light = new vl::Light(0);
    vl::ref<vl::Effect> ground_fx = new vl::Effect;
    ground_fx->shader()->setRenderState( light.get() );
    ground_fx->shader()->enable(vl::EN_LIGHTING);
    ground_fx->shader()->enable(vl::EN_DEPTH_TEST);

    // ground

    vl::ref<vl::Geometry> ground;
    ground = vl::makeGrid( vl::vec3(0,-30,0), size*1.1f, size*1.1f, 20, 20 );
    ground->computeNormals();
    sceneManager()->tree()->addActor(ground.get(), ground_fx.get() );

    vl::ref<vl::ResourceDatabase> res_db = vl::loadResource("/3rdparty/pknight/tris.md2");

    vl::ref<vl::MorphingCallback> morph_cb1 = new vl::MorphingCallback;
    morph_cb1->init(res_db.get());

    vl::ref<vl::Effect> effect[4] = { new vl::Effect, new vl::Effect, new vl::Effect, new vl::Effect };
    const char* texname[] = { "/3rdparty/pknight/evil.tif", "/3rdparty/pknight/knight.tif", "/3rdparty/pknight/ctf_r.tif", "/3rdparty/pknight/ctf_b.tif" };
    for(int i=0; i<4; ++i)
    {
      effect[i]->shader()->setRenderState( light.get() );
      effect[i]->shader()->enable(vl::EN_LIGHTING);
      effect[i]->shader()->enable(vl::EN_DEPTH_TEST);
      vl::ref<vl::Texture> texture = new vl::Texture;
      texture->prepareTexture2D(texname[i], vl::TF_RGBA);
      effect[i]->shader()->gocTextureUnit(0)->setTexture( texture.get() );

      if (glsl_vertex_blend)
      {
        vl::ref<vl::GLSLProgram> glsl = effect[i]->shader()->gocGLSLProgram();
        effect[i]->shader()->gocGLSLProgram()->attachShader(new vl::GLSLVertexShader("glsl/vertex_blend.vs"));
      }
    }

    /* multi instancing */
    for(int i=0; i<actor_count; i++)
    {
      float x = rand() % RAND_MAX / (float)RAND_MAX - 0.5f;
      float z = rand() % RAND_MAX / (float)RAND_MAX - 0.5f;
      x *= size;
      z *= size;
      vl::ref<vl::Actor> morph_act2 = new vl::Actor;
      vl::ref<vl::MorphingCallback> morph_cb2 = new vl::MorphingCallback;
      morph_cb2->bindActor( morph_act2.get() );
      morph_cb2->initFrom( morph_cb1.get() );

      morph_act2->setEffect( effect[i%4].get() );

      sceneManager()->tree()->addActor( morph_act2.get() );
      morph_act2->setTransform( new vl::Transform );
      morph_act2->transform()->setLocalMatrix( vl::mat4::getTranslation(x,-morph_act2->lod(0)->boundingBox().minCorner().y(),z) );
      morph_act2->transform()->computeWorldMatrix(NULL);

      switch(i % 5)
      {
        case 0: morph_cb2->setAnimation(0,   39,  1.5f); break; // stand
        case 1: morph_cb2->setAnimation(40,  45,  1.5f); break; // run
        case 2: morph_cb2->setAnimation(46,  53,  1.5f); break; // attack
        case 3: morph_cb2->setAnimation(112, 122, 1.5f); break; // wave
        case 4: morph_cb2->setAnimation(190, 197, 1.5f); break; // die
      }

      morph_cb2->startAnimation();
      morph_cb2->setGLSLVertexBlendEnabled(glsl_vertex_blend);
    }
  }
 void initEvent()
 {
   vl::Log::notify(appletInfo());
   showSimplePipe();
   showText();
 }
    virtual void initEvent()
    {
        vl::Log::notify(appletInfo());

        mCameraLightType = Disable;

        // setup our simple scene with a plane and a few columns

        mLightFx = new vl::Effect;
        mLightFx->shader()->enable(vl::EN_LIGHTING); /* IMPORTANT! */
        mLightFx->shader()->enable(vl::EN_DEPTH_TEST);

        vl::ref<vl::Geometry> ground = vl::makeGrid( vl::vec3(0,0,0), 20, 20, 100,100 );
        ground->computeNormals();
        sceneManager()->tree()->addActor(ground.get(), mLightFx.get());

        for(int i=0; i<9; ++i)
        {
            vl::ref<vl::Geometry> pillar = vl::makeCylinder( vl::vec3(6,2,-4*1.1f + i*1.1f), 1, 4, 100, 100, true, false);
            pillar->computeNormals();
            sceneManager()->tree()->addActor(pillar.get(), mLightFx.get());
        }

        for(int i=0; i<5; ++i)
        {
            vl::ref<vl::Geometry> pillar = vl::makeCylinder( vl::vec3(-3,2,-2*1.1f + i*1.1f), 1, 4, 100, 100, true, false);
            pillar->computeNormals();
            sceneManager()->tree()->addActor(pillar.get(), mLightFx.get());
        }

        // light setup

        // A typical OpenGL implementation supports up to 8 lights at the same time. It means that your scene can have
        // as many lights as you want but each object can be lit "only" by 8 lights at a time, this is usually never the
        // case as lighting absorbs considerable computational resources.

        // In our example each object will be lit up to 5 lights at the same time.

        mLight0 = new vl::Light;
        mLight1 = new vl::Light;
        mLight2 = new vl::Light;
        mLight3 = new vl::Light;
        mLight4 = new vl::Light;

        // Add the lights to the shader in order to use them (we save light #4 for the camera)
        mLightFx->shader()->setRenderState( mLight0.get(), 0 );
        mLightFx->shader()->setRenderState( mLight1.get(), 1 );
        mLightFx->shader()->setRenderState( mLight2.get(), 2 );
        mLightFx->shader()->setRenderState( mLight3.get(), 3 );

        // Define the light diffuse color.
        // See the OpenGL Programmer's Guide for more details about the OpenGL lighting model and equations.
        mLight0->setDiffuse(vl::red);
        mLight1->setDiffuse(vl::green);
        mLight2->setDiffuse(vl::blue);
        mLight3->setDiffuse(vl::white);
        mLight4->setDiffuse(vl::white);

        // Setup lights #0, #1 and #2 as positional lights with constant, linear and quadratic attenuation.
        // Again, see the OpenGL Programmer's Guide for more details about the OpenGL lighting model and equations.
        mLight0->setPosition(vl::fvec4(0,0,0,1)); /* default */
        mLight0->setConstantAttenuation(1.0f);
        mLight0->setLinearAttenuation(0.0f);
        mLight0->setQuadraticAttenuation(0.0f);

        mLight1->setPosition(vl::fvec4(0,0,0,1)); /* default */
        mLight1->setConstantAttenuation(0.0f);
        mLight1->setLinearAttenuation(1.0f);
        mLight1->setQuadraticAttenuation(0.0f);

        mLight2->setPosition(vl::fvec4(0,0,0,1)); /* default */
        mLight2->setConstantAttenuation(0.0f);
        mLight2->setLinearAttenuation(0.0f);
        mLight2->setQuadraticAttenuation(1.0f);

        // Setup light #3 as a spot light.
        // Valid values are from 0.0f to 90.0f plus the special value 180.0f (default) which disables the spot lighting.
        mLight3->setSpotCutoff(45.0f);
        mLight3->setSpotExponent(5.0f);
        mLight3->setSpotDirection(vl::fvec3(1,0,0));
        // A spot light is essentially a special positional light so these apply to spot lights as well.
        mLight3->setConstantAttenuation(1.0f);
        mLight3->setLinearAttenuation(0.0f);
        mLight3->setQuadraticAttenuation(0.0f);

        // Setup light's Transform to animate them
        mLight0_Transform = new vl::Transform;
        mLight1_Transform = new vl::Transform;
        mLight2_Transform = new vl::Transform;
        mLight3_Transform = new vl::Transform;
        rendering()->as<vl::Rendering>()->transform()->addChild(mLight0_Transform.get());
        rendering()->as<vl::Rendering>()->transform()->addChild(mLight1_Transform.get());
        rendering()->as<vl::Rendering>()->transform()->addChild(mLight2_Transform.get());
        rendering()->as<vl::Rendering>()->transform()->addChild(mLight3_Transform.get());
        // light 0..3 follow the relative transform
        mLight0->bindTransform(mLight0_Transform.get());
        mLight1->bindTransform(mLight1_Transform.get());
        mLight2->bindTransform(mLight2_Transform.get());
        mLight3->bindTransform(mLight3_Transform.get());
        // light 4 follows the camera
        mLight4->bindTransform(NULL);

        // add a white sphere for each light to have a better visual feedback of the light animation.
        vl::ref<vl::Geometry> bulb = vl::makeUVSphere(vl::vec3(0,0,0), 0.5f);
        vl::ref<vl::Effect> bulb_fx = new vl::Effect;
        bulb_fx->shader()->enable(vl::EN_DEPTH_TEST);
        bulb_fx->shader()->gocColor()->setValue(vl::white);
        sceneManager()->tree()->addActor(bulb.get(), bulb_fx.get(), mLight0_Transform.get());
        sceneManager()->tree()->addActor(bulb.get(), bulb_fx.get(), mLight1_Transform.get());
        sceneManager()->tree()->addActor(bulb.get(), bulb_fx.get(), mLight2_Transform.get());
        sceneManager()->tree()->addActor(bulb.get(), bulb_fx.get(), mLight3_Transform.get());

        // Simple text to inform the user of the currently active light setup.
        vl::ref<vl::Effect> text_fx = new vl::Effect;
        text_fx->shader()->enable(vl::EN_BLEND);
        mText = new vl::Text;
        mText->setFont( vl::defFontManager()->acquireFont("/font/bitstream-vera/VeraMono.ttf", 8) );
        mText->setAlignment( vl::AlignHCenter | vl::AlignTop );
        mText->setViewportAlignment( vl::AlignHCenter | vl::AlignTop );
        mText->translate(0,-10,0);
        sceneManager()->tree()->addActor(mText.get(), text_fx.get());
        updateText();
    }
  void initEvent()
  {
    vl::Log::notify(appletInfo());

    /* bind Transform */
    mTransform_Left  = new vl::Transform;
    mTransform_Right = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild( mTransform_Left.get() );
    rendering()->as<vl::Rendering>()->transform()->addChild( mTransform_Right.get() );

    /* define the Effect to be used */
    vl::ref<vl::Effect> effect = new vl::Effect;
    /* enable depth test and lighting */
    effect->shader()->enable(vl::EN_DEPTH_TEST);
    /* enable lighting and material properties */
    effect->shader()->setRenderState( new vl::Light, 0 );
    effect->shader()->enable(vl::EN_LIGHTING);
    effect->shader()->gocMaterial()->setDiffuse( vl::fvec4(1.0f,1.0f,1.0f,0.5f) );
    effect->shader()->gocLightModel()->setTwoSide(true);
    /* enable alpha blending */
    effect->shader()->enable(vl::EN_BLEND);

    /* load the object*/
    vl::ref<vl::Geometry> geom_no_sort;
    vl::ref<vl::Geometry> geom_sorted;
    vl::ref<vl::ResourceDatabase> res_db;
    res_db = vl::loadResource(mFileName); if ( res_db && res_db->count<vl::Geometry>() ) geom_no_sort = res_db->get<vl::Geometry>(0);
    res_db = vl::loadResource(mFileName); if ( res_db && res_db->count<vl::Geometry>() ) geom_sorted  = res_db->get<vl::Geometry>(0);

    if (!geom_no_sort->normalArray())
      geom_no_sort->computeNormals();

    if (!geom_sorted->normalArray())
      geom_sorted->computeNormals();

    /*
     if you want you can do

     geom_sorted->setDisplayListEnabled(true);

     or

     geom_sorted->setBufferObjectEnabled(true);

     but note that in this case the DepthSortCallback will schedule an update of the BufferObject or of the display list
     at every frame! This will almost centainly make the use of BufferObjects or display lists useful if not harmful, performance-wise.
    */

    /* add the two objects to the scene manager */
    vl::ref<vl::Actor> actor_no_sort = sceneManager()->tree()->addActor( geom_no_sort.get(), effect.get(), mTransform_Left.get() );
    vl::ref<vl::Actor> actor_sort    = sceneManager()->tree()->addActor( geom_sorted.get(),  effect.get(), mTransform_Right.get() );
    /* install the vl::DepthSortCallback that will depth-sort each primitive of the Actor upon rendering */
    actor_sort->actorEventCallbacks()->push_back( new vl::DepthSortCallback );

    /* compute the appropriate offset to be used in updateTransforms() */
    geom_no_sort->computeBounds();
    geom_sorted->computeBounds();
    mOffset = float( (geom_no_sort->boundingSphere().radius() + geom_sorted->boundingSphere().radius()) * 0.5 );

    /* positions the two objects next to one another */
    updateTransforms();

    /* Position the camera to nicely see the objects in the scene. 
       You must call this function after having positioned your objects in the scene! */
    trackball()->adjustView( sceneManager(), vl::vec3(0,0,1), vl::vec3(0,1,0), 1.0f );
  }
  void initEvent()
  {
    if (!vl::Has_GLSL)
    {
      vl::Log::error("OpenGL Shading Language not supported.\n");
      vl::Time::sleep(2000);
      exit(1);
    }

    vl::Log::notify(appletInfo());

    mTransform = new vl::Transform;

    // generate torus, with normals and uv coords
    vl::ref<vl::Geometry> model = vl::makeTorus( vl::vec3(0,0,0), 10, 2, TORUS_SEGS, TORUS_SEGS, 2.0f );
    model->transform( vl::mat4::getRotation( 45.0f, 1.0f, 1.0f, 0.0f ) );

    // setup 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);
    effect->shader()->enable(vl::EN_CULL_FACE);
    mTorus = sceneManager()->tree()->addActor( model.get(), effect.get(), mTransform.get() );

    // setup texture
    vl::ref<vl::Texture> texture0 = new vl::Texture;
    texture0->prepareTexture2D("images/normalmap.jpg", vl::TF_RGBA);
    effect->shader()->gocTextureSampler(0)->setTexture(texture0.get());
    texture0->getTexParameter()->setAnisotropy(16.0);
    texture0->getTexParameter()->setMagFilter(vl::TPF_LINEAR);
    texture0->getTexParameter()->setMinFilter(vl::TPF_LINEAR_MIPMAP_LINEAR);

    // setup GLSL shader
    mGLSL = effect->shader()->gocGLSLProgram();
    mGLSL->attachShader( new vl::GLSLVertexShader("/glsl/bumpmap.vs") );
    mGLSL->attachShader( new vl::GLSLFragmentShader("/glsl/bumpmap.fs") );
    // samper0
    vl::ref<vl::Uniform> sampler0 = new vl::Uniform("sampler0");
    sampler0->setUniformI(0);
    mGLSL->setUniform( sampler0.get() );
    // light_obj_space_pos
    mLightObjSpacePosition = new vl::Uniform("light_obj_space_pos");
    mGLSL->setUniform( mLightObjSpacePosition.get() );

    // compute the tangent vector for each vertex

    vl::ref<vl::ArrayFloat3> tangent = new vl::ArrayFloat3;
    tangent->resize( model->vertexArray()->size() );

    vl::Geometry::computeTangentSpace(
      model->vertexArray()->size(), 
      (vl::fvec3*)model->vertexArray()->ptr(), 
      (vl::fvec3*)model->normalArray()->ptr(), 
      (vl::fvec2*)model->texCoordArray(0)->ptr(),
      model->drawCalls()->at(0),
      tangent->begin(), 
      NULL );

    // bind the tangent vertex attribute
    mGLSL->linkProgram();
    // note that you need to link the GLSL program before calling this
    int tangent_idx = mGLSL->getAttribLocation("tangent"); VL_CHECK( tangent_idx != -1 );
    model->setVertexAttribArray(tangent_idx, tangent.get() );

    // visualize the TBN vectors
    visualizeTangentSpace( model.get(), tangent.get() );
  }
  virtual void initEvent()
  {
    vl::Log::notify(appletInfo());

    // transform used for the moving cube and star

    vl::ref< vl::Transform > transf = new vl::Transform;
    rendering()->as<vl::Rendering>()->transform()->addChild(transf.get());

    // effect for 2d rendering

    vl::ref<vl::Effect> pixel_fx = new vl::Effect;
    pixel_fx->shader()->enable(vl::EN_BLEND);
    pixel_fx->shader()->enable(vl::EN_ALPHA_TEST);
    pixel_fx->shader()->gocAlphaFunc()->set(vl::FU_GEQUAL, 0.9f);

    // points rendering

    vl::ref<vl::ImagePBO> circle16 = new vl::ImagePBO("/images/circle16.png");

    mPoints = new vl::DrawPixels;
    for(int i=0; i<1000; ++i)
    {
      vl::ref<vl::DrawPixels::Pixels> pixels = new vl::DrawPixels::Pixels(circle16.get(), 0,0);
      mPoints->draws()->push_back( pixels.get() );
      vl::ivec2 pos;
      pos.x() = int(openglContext()->width()  / 2.0 + rand()%300 - 150);
      pos.y() = int(openglContext()->height() / 2.0 + rand()%300 - 150);
      pixels->setPosition(pos);
      pixels->setAlign(vl::AlignHCenter | vl::AlignVCenter);
    }

    mPoints->generatePixelBufferObjects(vl::BU_STATIC_DRAW, true);

    sceneManager()->tree()->addActor( mPoints.get(), pixel_fx.get(), NULL )->setRenderRank(0);

    // split star rendering

    vl::ref<vl::ImagePBO> star_img = new vl::ImagePBO("/images/star.png");

    int w = star_img->width() / 2;
    mStar1 = new vl::DrawPixels::Pixels( star_img.get(), 0, 0, 0, 0, w, w );
    mStar2 = new vl::DrawPixels::Pixels( star_img.get(), 0, 0, w, w, w, w );
    mStar3 = new vl::DrawPixels::Pixels( star_img.get(), 0, 0, w, 0, w, w);
    mStar4 = new vl::DrawPixels::Pixels( star_img.get(), 0, 0, 0, w, w, w);

    mStar1->setAlign(vl::AlignRight|vl::AlignTop);
    mStar2->setAlign(vl::AlignLeft|vl::AlignBottom);
    mStar3->setAlign(vl::AlignLeft|vl::AlignTop);
    mStar4->setAlign(vl::AlignRight|vl::AlignBottom);

    mStar = new vl::DrawPixels;
    mStar->draws()->push_back( mStar1.get() );
    mStar->draws()->push_back( mStar2.get() );
    mStar->draws()->push_back( mStar3.get() );
    mStar->draws()->push_back( mStar4.get() );

    mStar->generatePixelBufferObjects(vl::BU_STATIC_DRAW, true);

    sceneManager()->tree()->addActor( mStar.get(), pixel_fx.get(), transf.get() )->setRenderRank(1);

    // moving cube

    vl::ref<vl::Effect> cube_fx = new vl::Effect;
    cube_fx->shader()->enable(vl::EN_DEPTH_TEST);
    cube_fx->shader()->enable(vl::EN_LIGHTING);
    cube_fx->shader()->setRenderState( new vl::Light, 0 );

    vl::ref<vl::Geometry> cube = vl::makeBox( vl::vec3(0,0,0), 1, 1, 1 );
    cube->computeNormals();
    mCube = sceneManager()->tree()->addActor(cube.get(), cube_fx.get(), transf.get() );
    mCube->setRenderRank(2); // draw after 2d objects
  }
  void initEvent()
  {
    vl::Log::print(appletInfo());

    /* configure how many objects are there forming the ring */
    const int ring_obj_count = 20;

    /* define a LOD evaluator with 3 disance ranges: [0] --- 70 --- 150 --- [inf] */
    vl::ref<vl::DistanceLODEvaluator> lod_eval = new vl::DistanceLODEvaluator;
    lod_eval->addDistanceRange(70);
    lod_eval->addDistanceRange(150);

    /* to be used later */
    vl::ref<vl::Light> light = new vl::Light(0);
    vl::ref<vl::Shader> wire_sh = new vl::Shader;
    vl::ref<vl::Shader> fill_sh = new vl::Shader;
    vl::ref<vl::Shader> wave_sh = new vl::Shader;

    /* fill pass */
    fill_sh->enable(vl::EN_DEPTH_TEST);
    fill_sh->enable(vl::EN_CULL_FACE);
    fill_sh->enable(vl::EN_LIGHTING);
    fill_sh->gocMaterial()->setFrontDiffuse( vl::white );
    fill_sh->gocPolygonMode()->set(vl::PM_FILL, vl::PM_FILL); // note this is default
    fill_sh->setRenderState( light.get() );

    /* wire pass */
    wire_sh->enable(vl::EN_DEPTH_TEST);
    wire_sh->enable(vl::EN_LIGHTING);
    wire_sh->enable(vl::EN_BLEND); // for line smoothing
    wire_sh->enable(vl::EN_LINE_SMOOTH);
    wire_sh->enable(vl::EN_POLYGON_OFFSET_LINE);
    wire_sh->gocHint()->setLineSmoothHint(vl::HM_NICEST);
    wire_sh->gocMaterial()->setFlatColor( vl::royalblue );
    wire_sh->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE);
    wire_sh->gocPolygonOffset()->set(-1.0f, -1.0f);
    wire_sh->setRenderState( light.get() );

    /* wave pass */
    wave_sh->enable(vl::EN_BLEND); // for line smoothing
    wave_sh->enable(vl::EN_LINE_SMOOTH);
    wave_sh->gocHint()->setLineSmoothHint(vl::HM_NICEST);
    wave_sh->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE);

    /* animated wave actor has a single Effect LOD */
    vl::ref<vl::Effect> wave_fx = new vl::Effect;
    wave_fx->setLOD( 0, wave_sh.get() );

    /* add wave actor */
    vl::ref<vl::Actor> wave_act = sceneManager()->tree()->addActor(NULL, wave_fx.get(), NULL);
    /* install actor animation callback. */
    wave_act->actorEventCallbacks()->push_back( new WaveActorAnimator(wave_act.get()) );
    /* install the LOD evaluator */
    wave_act->setLODEvaluator(lod_eval.get());

    /* effect used by the objects forming a ring around the central wave */
    vl::ref<vl::Effect> ring_fx = new vl::Effect;
    ring_fx->setLOD( 0, fill_sh.get(), wire_sh.get() ); // LOD 0: pass #1 = fill_sh + pass #2 = wire_sh
    ring_fx->setLOD( 1, fill_sh.get() ); // LOD 1: pass #1 = fill_sh
    ring_fx->setLOD( 2, wire_sh.get() ); // LOD 2: pass #1 = wire_sh
    
    /* install the LOD evaluator to be used with the ring objects */
    ring_fx->setLODEvaluator(lod_eval.get());

    /* ring element lod #0 */
    vl::ref<vl::Geometry> geom_0 = vl::makeIcosphere(vl::vec3(0,0,0),10,1);
    geom_0->computeNormals();

    /* ring element lod #1 */
    vl::ref<vl::Geometry> geom_1 = vl::makeBox(vl::vec3(0,0,0),6,6,6);
    geom_1->computeNormals();

    /* ring element lod #2 */
    vl::ref<vl::Geometry> geom_2 = vl::makePyramid(vl::vec3(0,0,0),6,6);
    geom_2->computeNormals();

    /* generate the ring of objects */
    for(int i=0;i<ring_obj_count; i++)
    {
      /* define actor position and add it to the scene */
      vl::ref<vl::Transform> tr = new vl::Transform;
      vl::Real t = 360.0f / ring_obj_count * i;
      vl::vec3 v = vl::mat4::getRotation(t,0,1,0) * vl::vec3(35,0,0);
      tr->setLocalMatrix( vl::mat4::getTranslation(v) );

      rendering()->as<vl::Rendering>()->transform()->addChild(tr.get());
      
      vl::ref<vl::Actor> act = sceneManager()->tree()->addActor( NULL, ring_fx.get(), tr.get() );

      /* define which geometry to use for each LOD */
      act->setLod(0, geom_0.get());
      act->setLod(1, geom_1.get());
      act->setLod(2, geom_2.get());

      /* install the LOD evaluator*/
      act->setLODEvaluator(lod_eval.get());
    }
  }