Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

Picking and Selection Tutorial

This tutorial demonstrates how to use the vl::RayIntersector class to interactively pick and select objects in the scene.

In this tutorial we will populate the scene with a few random objects. Then when the mouse is pressed we compute the ray projected from the mouse click position towards the scene and use it to compute the intersections point. If any intersection is found we highlight the intersection point by moving there a green sphere.

[From App_Picking.hpp]

class App_Picking: public BaseDemo
{
public:

  void mouseDownEvent(vl::EMouseButton, int x, int y)
  {
    vl::Camera* camera = vl::VisualizationLibrary::rendering()->as<vl::Rendering>()->camera();

    // convert Y coordinates to the OpenGL conventions
    y = openglContext()->height() - y;
    // compute the ray passing through the selected pixel
    vl::Ray ray = camera->computeRay(x,y);
    // instance our ray-intersector
    vl::RayIntersector intersector;
    // compute a frustum along the ray to accelerate the intersection test
    intersector.setFrustum( camera->computeRayFrustum( x,y ) );
    // compute the intersections!
    // (1) short way
    intersector.intersect(ray, sceneManager());
    // (2) long way
    /*
    // specify the Actor[s] to be tested
    intersector.actors()->clear();
    sceneManager()->appendActors( *intersector.actors() );
    // set the intersecting ray
    intersector.setRay(ray);
    // run intersection test
    intersector.intersect();
    */

    // inspect our intersections, the intersections returned are sorted according to their distance, the first one is the closest.
    if (intersector.intersections().size())
    {
      // highlight the intersection point by moving the green sphere there
      mIntersectionPoint->setLocalMatrix( vl::mat4() );
      mIntersectionPoint->translate( intersector.intersections()[0]->intersectionPoint() );
      mIntersectionPoint->computeWorldMatrix();

      // print the name of the picked object
      vl::Log::print( vl::Say("Intersections detected = %n (%s).\n") << intersector.intersections().size() << intersector.intersections()[0]->actor()->name() );
    }
    else
      vl::Log::print("No intersections detected.\n");
  }

  virtual void initEvent()
  {
    BaseDemo::initEvent();

    // 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->setName(geom->name());
      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 = vlut::makeUVSphere(vl::vec3(0,0,0), 0.1f);
    intersection_point_geom->computeNormals();
    intersection_point_geom->setColorArray(vlut::green);
    vl::Actor* intersection_point_act = sceneManager()->tree()->addActor( intersection_point_geom.get(), fx.get(), new vl::Transform );
    mIntersectionPoint = intersection_point_act->transform();
  }

  // generate random objects
  vl::ref<vl::Geometry> randomObject()
  {
    vl::ref<vl::Geometry> geom;
    // random shape
    switch(rand() % 6)
    {
      case 0: geom = vlut::makeIcosphere(vl::vec3(0,0,0), 1, 2, false); break;
      case 1: geom = vlut::makeBox(vl::vec3(0,0,0), 1, 1, 1); break;
      case 2: geom = vlut::makeCone(vl::vec3(0,0,0),1,1); break;
      case 3: geom = vlut::makeUVSphere(vl::vec3(0,0,0),1); break;
      case 4: geom = vlut::makeCylinder(vl::vec3(0,0,0),1,1); break;
      case 5: geom = vlut::makeTorus(vl::vec3(0,0,0),2,0.5f,20,20); break;
    }
    // random color
    geom->setColorArray( vl::fvec4((float)vl::randomMinMax(0,1), (float)vl::randomMinMax(0,1), (float)vl::randomMinMax(0,1),1.0f) );
    // normals are needed for lighting
    geom->computeNormals();
    return geom;
  }

protected:
  vl::Transform* mIntersectionPoint;
};

// Have fun!

Visualization Library v2010.06 Reference Documentation
Copyright 2005-2009 Michele Bosi. All rights reserved.
Updated on Tue Jun 1 00:57:08 2010.
Permission is granted to use this page to write and publish articles regarding Visualization Library.