### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Read OpenGLContent mouse position and convert back to coords.  (Read 3199 times)

#### wp

• Hero Member
• Posts: 12287
##### Re: Read OpenGLContent mouse position and convert back to coords.
« Reply #15 on: May 21, 2024, 04:58:08 pm »
I have the impression that you want to click on the vertices of the OGL model, "nodes" in your words, right? In this case, since there are only a few nodes you could iterate over the nodes, calculate the screen point and compare with the click position (and allow for some tolerance). Calculation of the screen point can be done by the inverse of your gluUnproject: gluProject
Code: Pascal  [Select][+][-]
1. type
2.   TOpenGLPoint = record
3.     X, Y, Z: GLDouble;
4.   end;
5.
6. function CalcOpenGLScreenPoint(P: TOpenGLPoint): TPoint;
7. var
8.   viewport:   array[0..3]  of Integer;
9.   modelview:  array[0..15] of GLDouble;
10.   projection: array[0..15] of GLDouble;
11.   X,Y,Z: Double;
12. begin
13.   glGetDoublev(GL_MODELVIEW_MATRIX, @modelview );
14.   glGetDoublev(GL_PROJECTION_MATRIX, @projection );
15.   glGetIntegerv(GL_VIEWPORT, @viewport);
16.
17.   gluProject(P.X, P.Y, P.Z, @modelView, @projection, @viewport, @X, @Y, @Z);
18.   Result.X := round(X);
19.   Result.Y := viewport[3] - round(Y);
20. end;
21.
22. function TForm1.FindClickedNodeIndex(X, Y: Integer): Integer;
23. // Assuming that your model consists of an array of vertices (TOpenGLPoint)
24. const
25.   Tolerance = 5;
26. var
27.   i: Integer;
28.   P: TPoint;
29. begin
30.   for i := 0 to Length(Vertices)-1 do
31.   begin
32.     P := CalcOpenGLScreenPoint(Vertices[i]);
33.     if (abs(P.X - X) < Tolerance)) and (abs(P.Y - Y) < Tolerance) then
34.     begin
35.       Result := i;
36.       exit;
37.     end;
38.   end;
39.   Result := -1;
40. end;

Attaching a small OpenGL project which demonstrates this. The nodes in the demo are at the corners/endpoints of the table-like object. Ctrl-click on them and the coordinates of the clicked vertex (in model coordinates) will be displayed in the blue label at the bottom.
P.S. Sorry for mentioning the integer issue in my previous post, I was just confused by the different order of declarations and procedure calls.
« Last Edit: May 21, 2024, 06:50:03 pm by wp »

#### ranny

• Jr. Member
• Posts: 81
##### Re: Read OpenGLContent mouse position and convert back to coords.
« Reply #16 on: June 26, 2024, 04:31:43 pm »
Hi,

Sorry for so long since I started this post.  I have had a lot of difficulties with other parts of my code, but I did find a fix for this - not glamorous but it works perfectly well.

I have nodes, elements, loads, restrictions and fixings in my model that I want to be able to select.  if I want to select a node then the nearest node to the cursor is what I want.  For loads etc. it has to be the nearest load that is selected but loads can only exist at nodes and there may be 100 nodes and only 2 or 3 loads anywhere in the model.

Considering selection of nodes, currently when the node positions are plotted the node number is plotted next to it.  The routine to write the node number is beyond my total understanding but it places it based on the actual viewport location based on the top
left of the form (opengl object in the form actually).  So every time a node number is plotted, I store that X,Y pair in an array.  When I want to select a node, on MouseDown the screen position X,Y is compared to the stored X,Y's from placement of the node numbers and works out which is closest.  Works perfectly. For loads etc. the X,Y is stored where the load number would be in a separate array and that is used when I want to select only loads.  And so on for other features like restraints.

I know it is not very clever but it does work very well and it has allowed me to progress with other aspects of the program.

Thanks for the support.

#### ranny

• Jr. Member
• Posts: 81
##### Re: Read OpenGLContent mouse position and convert back to coords.
« Reply #17 on: June 27, 2024, 04:37:23 pm »
WP - I owe you an apology.  When I went to add my latest post on this subject, I did not see your post as it had moved to a new page and I just assumed that the last comments were those on page 1.

Now that i have seen your suggestion, it is a similar approach to what I took, although your version is much tidier and surely the best way to do it, although I worked out my version not knowing your post existed - that could have saved me some time!

You are working with vertices as a record but the original code for the maths (20 years old actually) were a bunch of individual arrays that I am working with, but it works fine.  The only comment I have on your code is that in your loop to find the closest "node" you jump if the check for less than tolerance is met whereas there could be a closer node.  Also you could be selecting from a greater distance than tolerance could ever be fulfilled, as your demo shows.  So I opted for checking the distance between mouse position and all nodes and selection is the shortest distance from amongst all.