Pick an point, "ray-point intersection"

• I am trying to implement a ray-point picking, but it does not work...

I found some information about unprojection here:
http://www.dyn-lab.com/articles/pick-selection.html
http://stackoverflow.com/questions/2093096/implementing-ray-picking

I implemented this function from the second link:
@normalised_x = 2 * mouse_x / win_width - 1
normalised_y = 1 - 2 * mouse_y / win_height
// note the y pos is inverted, so +y is at the top of the screen

unviewMat = (projectionMat * modelViewMat).inverse()

near_point = unviewMat * Vec(normalised_x, normalised_y, 0, 1)
camera_pos = ray_origin = modelViewMat.inverse().col(4)
ray_dir = near_point - camera_pos@

The result is that:
@void OpenGL::unproject(int x, int mx, int y, int my, int z,
QMatrix4x4 ModelView, QMatrix4x4 Projection)
{
float normalized_x, normalized_y;
QMatrix4x4 Unview;
QVector4D near_point, camera_pos, ray_dir, ray_origin;

``````normalized_x = 2.0 * x/mx - 1.0;
normalized_y = 1.0 - 2.0 * y/my;

Unview = (Projection*ModelView).inverted();

near_point = Unview * QVector4D(normalized_x, normalized_y, 0, 1);
camera_pos = ray_origin = ModelView.inverted().column(3);
ray_dir = (near_point - camera_pos).normalized();
``````

}@

And to find the closest point to the ray I implemented this function:
@int OpenGL::closestPoint(QVector4D end_point, QVector4D ray_dir,
QVector3D *vertices, int num_vertices)
{
int p, selected = -1;
float d, closest = numeric_limits<float>::max();
QVector3D O, dir, P;

``````O = end_point.toVector3DAffine();
dir = ray_dir.toVector3DAffine();

/* For each point calculates the distance and check if it is the smallest */
for(p = 0; p < num_vertices; p++)
{
P = vertices[p];
d = P.distanceToLine(O, dir);
if(d < closest)
{
closest = d;
selected = p;
}
}
return selected;
``````

}@

But they do not work... The point returned is always the same, do not matter the position of the mouse on the screen...
What can I doing wrong?
Does anyone tried something like that?
Is there some simplest way to do that using some Qt library?

• Hi belimawr, I just looked semantically through your code. Does the transformation work well for your points?

@
O = end_point.toVector3DAffine();
dir = ray_dir.toVector3DAffine();@

What does
@ d = P.distanceToLine(O, dir);
@

return?

• Franku,

I am not sure about which transformation you are talking about. Is the transformation in PaintGL, with the matrices ModelView and Projection or about "toVector3DAffine" with I am using in closestPoint?

The matrices ModelView and Projectiom works well.

But the "toVector3DAffine" I think that it is working, I have not checked yet... I need to imagine some kind of test to do which this function.

The function distanceToLine receives a point (O), and a vector (dir) to calculate the distance of point P to the line that starts in O and has the direction dir.

• Hi, hmm. With my comment above the lines 1. and 2. there's a transformation done from QVector4D into the 3D points O and dir. These two points span up a line (more exactly the ray). The code is from closestPoint.

And with the second code snippet from above there is a distance being calculated using the coordinates spanning that line using the 3D coordinates and the 3D point P. It is from closestPoint, too.

My idea was to step with a debugger through the code and see which values are calculated each time to get an idea of what your code is doing exactly. Since it is 3D you probably could calculate some things by hand and see if your code does the same. (I am not familiar with coordinate transform and such things, but I wanted to mention the idea since it might help you.)

• Franku,

That is a good idea, I will try something like that today.

Other idea that I had is draw the ray and see if it is right (probably easier that calculate every thing).

Yesterday I have started this drawing debug and I could see that the vector dir looks to be in the wrong direction... -dir looks more right.

Thanks for your help, today I will do more tests and when a get more results I will post here.

• FYI, If you want to just implement object/polygon picking, a very straightforward approach is the color based picking:

http://content.gpwiki.org/index.php/OpenGL_Selection_Using_Unique_Color_IDs

I'm using that in ToyBlocks and it works like a dream.

• [quote author="matti-" date="1344789496"]FYI, If you want to just implement object/polygon picking, a very straightforward approach is the color based picking:

http://content.gpwiki.org/index.php/OpenGL_Selection_Using_Unique_Color_IDs

I'm using that in ToyBlocks and it works like a dream.[/quote]

I am not sure if it will work to me, because I ma using GLSL, programming my shaders and this kind of stuff...

Has you ever tried some thing like that? Use GLSL and shaders to draw the "normal" scene and this deprecated way to do the colour picking?

I have looked to code examples which GLSL and colour picking, but I never found anything....

However I will try it this week and post here the results.

• matti-, the colour picking worked!!!! Thank you very much!!

I always thought that I only can call the draw functions inside the paintGL, but I was wrong.

I just copied the paintGL into the mouse click event and changed the values in the colour buffer, and called glReadPixels. It is working in a perfect way!!!

Again, thank you very much!!!

• Aye its a nice shortcut into picking :)

The same mechanism can sort of be (ab)used for example to do occlusion testing like for eg lens flares.