Visualization Library v1.0.3

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

VL     Star     Watch     Fork     Issue

[Download] [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.cpp]

class App_Picking: public BaseDemo
{
public:

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

    // convert Y coordinates to the OpenGL conventions
    y = openglContext()->height() - y;
    // compute the ray passing through the selected pixel
    Ray ray = camera->computeRay(x,y);
    // instance our ray-intersector
    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()->extractActors( *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( mat4() );
      mIntersectionPoint->translate( intersector.intersections()[0]->intersectionPoint() );
      mIntersectionPoint->computeWorldMatrix();

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

  virtual void initEvent()
  {
    Log::notify(appletInfo());

    srand((int)time(NULL));

    // populate our scene with some random objects

    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)
    {
      // random color
      ref<Effect> fx = new Effect;
      fx->shader()->enable(EN_DEPTH_TEST);
      fx->shader()->enable(EN_LIGHTING);
      fx->shader()->gocLight(0)->setLinearAttenuation(0.025f);
      fx->shader()->gocMaterial()->setDiffuse( fvec4((float)random(0,1), (float)random(0,1), (float)random(0,1),1.0f) );

      ref<Geometry> geom = randomObject();
      Actor* act = sceneManager()->tree()->addActor( geom.get(), fx.get(), new Transform );
      act->setObjectName(geom->objectName().c_str());
      act->transform()->translate(x*displace, y*displace, z*displace);
      act->transform()->computeWorldMatrix();
    }

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

    // random color
    ref<Effect> fx = new Effect;
    fx->shader()->enable(EN_DEPTH_TEST);
    fx->shader()->enable(EN_LIGHTING);
    fx->shader()->gocLight(0)->setLinearAttenuation(0.025f);
    fx->shader()->gocMaterial()->setDiffuse( green );

    ref<Geometry> intersection_point_geom = makeUVSphere(vec3(0,0,0), 0.1f);
    intersection_point_geom->computeNormals();
    Actor* intersection_point_act = sceneManager()->tree()->addActor( intersection_point_geom.get(), fx.get(), new Transform );
    mIntersectionPoint = intersection_point_act->transform();
  }

  // generate random objects
  ref<Geometry> randomObject()
  {
    ref<Geometry> geom;
    // random shape
    switch(rand() % 7)
    {
      case 0: geom = makeIcosphere(vec3(0,0,0), 1, 2, false); break;
      case 1: geom = makeBox(vec3(0,0,0), 1, 1, 1); break;
      case 2: geom = makeCone(vec3(0,0,0),1,1); break;
      case 3: geom = makeUVSphere(vec3(0,0,0),1); break;
      case 4: geom = makeCylinder(vec3(0,0,0),1,1); break;
      case 5: geom = makeTorus(vec3(0,0,0),2,0.5f,20,20); break;
      case 6: geom = makeTeapot(vec3(0,0,0),2); break;
    }
    // normals are needed for lighting
    if (!geom->normalArray())
      geom->computeNormals();
    return geom;
  }

protected:
  Transform* mIntersectionPoint;
};

// Have fun!


Visualization Library v1.0.3 Reference Documentation
Copyright Michele Bosi. All rights reserved.
Updated on Tue Feb 7 2017 00:55:05.
Permission is granted to use this page to write and publish articles regarding Visualization Library.