August 3, 2012

belimawr belimawr
Lab Rat
20 posts

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:

  1. normalised_x = 2 * mouse_x / win_width - 1
  2. normalised_y = 1 - 2 * mouse_y / win_height
  3. // note the y pos is inverted, so +y is at the top of the screen
  4.  
  5. unviewMat = (projectionMat * modelViewMat).inverse()
  6.  
  7. near_point = unviewMat * Vec(normalised_x, normalised_y, 0, 1)
  8. camera_pos = ray_origin = modelViewMat.inverse().col(4)
  9. ray_dir = near_point - camera_pos

The result is that:

  1. void OpenGL::unproject(int x, int mx, int y, int my, int z,
  2.                     QMatrix4x4 ModelView, QMatrix4x4 Projection)
  3. {
  4.     int p_selecionada;
  5.     float normalized_x, normalized_y;
  6.     QMatrix4x4 Unview;
  7.     QVector4D near_point, camera_pos, ray_dir, ray_origin;
  8.  
  9.     normalized_x = 2.0 * x/mx - 1.0;
  10.     normalized_y = 1.0 - 2.0 * y/my;
  11.  
  12.     Unview = (Projection*ModelView).inverted();
  13.  
  14.     near_point = Unview * QVector4D(normalized_x, normalized_y, 0, 1);
  15.     camera_pos = ray_origin = ModelView.inverted().column(3);
  16.     ray_dir = (near_point - camera_pos).normalized();
  17. }

And to find the closest point to the ray I implemented this function:

  1. int OpenGL::closestPoint(QVector4D end_point, QVector4D ray_dir,
  2.                                     QVector3D *vertices, int num_vertices)
  3. {
  4.     int p, selected = -1;
  5.     float d, closest = numeric_limits<float>::max();
  6.     QVector3D O, dir, P;
  7.  
  8.     O = end_point.toVector3DAffine();
  9.     dir = ray_dir.toVector3DAffine();
  10.  
  11.     /* For each point calculates the distance and check if it is the smallest */
  12.     for(p = 0; p < num_vertices; p++)
  13.     {
  14.         P = vertices[p];
  15.         d = P.distanceToLine(O, dir);
  16.         if(d < closest)
  17.         {
  18.             closest = d;
  19.             selected = p;
  20.         }
  21.     }
  22.     return selected;
  23. }

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?

8 replies

August 7, 2012

franku franku
Hobby Entomologist
132 posts

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

  1.     O = end_point.toVector3DAffine();
  2.     dir = ray_dir.toVector3DAffine();

What does

  1.          d = P.distanceToLine(O, dir);

return?

 Signature 

Keep in mind: This, Jen, is the internet.
.. frank

August 9, 2012

belimawr belimawr
Lab Rat
20 posts

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.

August 9, 2012

franku franku
Hobby Entomologist
132 posts

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.)

 Signature 

Keep in mind: This, Jen, is the internet.
.. frank

August 10, 2012

belimawr belimawr
Lab Rat
20 posts

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.

August 12, 2012

matti- matti-
Ant Farmer
107 posts

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.

 Signature 

Author of MMark13

August 13, 2012

belimawr belimawr
Lab Rat
20 posts

matti- wrote:
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.

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.

August 16, 2012

belimawr belimawr
Lab Rat
20 posts

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!!!

August 16, 2012

matti- matti-
Ant Farmer
107 posts

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.

 Signature 

Author of MMark13

 
  ‹‹ multiple opengl screens      Feedback request for a Qt-based game engine featuring QML & Cocos2D ››

You must log in to post a reply. Not a member yet? Register here!