Visualization Library 2.1.0

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()->extractVisibleActors( *intersector.actors(), NULL );
// 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!