Skip to main content
GameDev.net gamedev.net
🔒 Locked

Picking Text

Started by Butter Apr 24, 2003 at 10:16 AM 3 replies 400+ views
Original Post
Butter
Butter
In my application I need to let the user pick objects by clicking on text labels associated with them. I can get the world coordinates of the mouse click using gluUnProject(). I also know the Raster position were I drew the label. I can generate a bounding rectangle for the label because I know the size of the font and the length of the label. I think that I need to find the intersection of the ray from the camera in the direction of the click coordinates and the plane that the label is in. Then check if the intersection is in the texts rectangle. Is my theory OK? How do I implement this? I''m really rusty on math. Is there a better way? Thanks for any help.
Butter
Butter
OK - say I have a gun in a FPS and I am trying to shoot a wall. When I click I get the mouse coordinates in screen coords. I can use gluUnProject to get the world coordinates of the click, and with the camera location and that I have a ray in to the scene. What is my next step to figure out if I hit the wall?
Trienco
Trienco
check of the ray intersects the wall? you already did the "hard" part, the rest is testing for intersection (but as you probably dont want to check if you hit that specific wall thats the point where a good hierarchy comes into play so you dont have to test every single object).

the much more interesting question is: as your gun isnt at your eyepoint, would you cheat and "shoot" the ray from your eye through the point? or get a target point this way and then align the gun to aim at that point and shoot (making it two intersection tests, one to find out where you want to shoot and one to see if you dont hit the guy ducking in front of you ,-) )
f@dzhttp://festini.device-zero.de
Roland
Roland
You have the rasterposition? You know the position of your label in 2D coordinates?
Why don't you use the 2D coordinaes of your mouseclick to determine if you hit it.

In 3D if you want to find out, if a rectangle was hit, you need your eyepos(e), the unprojected point(p) and three edges of the rectangle(r1,r2,r3), where r1 is between r2 and r3:


r1----r2
| |
r3----r4


Here is a bit of C++-pseudo Code, which should do the trick:



                
float e[3],p[3],r1[3],r2[r],r3[3]; // The vectors as described above

float d0,dm,dn,m,n; // used for calculation


float a[3] = { p[0] - e[0], p[1] - e[1], p[2] - e[2]},
b[3] = {r2[0] - r1[0], r2[1] - r1[1], r2[2] - r1[2]},
c[3] = {r3[0] - r1[0], r3[1] - r1[1], r3[2] - r1[2]},
d[3] = { e[0] - r1[0], e[1] - r1[1], e[2] - r1[2]};

// Calculate the determinants of the system of equations

d0 = a[0]*b[1]*c[2] - a[0]*b[2]*c[1] + b[2]*a[1]*c[0] + a[2]*b[0]*c[1] - b[1]*a[2]*c[0] - a[1]*b[0]*c[2];
dm = a[0]*c[2]*d[1] - a[0]*d[2]*c[1] - c[2]*a[1]*d[0] - a[2]*c[0]*d[1] + a[2]*d[0]*c[1] + d[2]*a[1]*c[0];
dn = -a[0]*b[2]*d[1] - a[1]*b[0]*d[2] + b[2]*a[1]*d[0] + a[0]*b[1]*d[2] + a[2]*b[0]*d[1] - b[1]*a[2]*d[0]
// Calculate m and n

m = D0 / Dm;
n = D0 / Dn;

// See if m and n are between 0 and 1

if ((m>=0.0) && (m<=1.0) && (n>=0.0) && (n<=1.0))
return true;
else
return false;


This code was created by using the vector equations for the ray and the plane:


e,p,r1,r2,r3,a,b,c,d,x are vectors
l,m,n are scalars

ray: x = e + l * (p-e)
plane: x = r1 + m * (r2-r1)+n * (r3-r1)
together: e + l * (p-e) = r1 + m * (r2-r1) + n * (r3-r1)
<=> e - r1 = -l *(p-e) + m * (r2-r1) + n * (r3-r1)

To make it a bit easier to read I set:
a = p-e
b = r2-r1
c = r3-r1
d = e-r1

Then the equation is:
d = -l*a + m * b + n * c

This vector equation can be split into three equations:

d.x = -l*a.x + m * b.x + n * c.x
d.y = -l*a.y + m * b.y + n * c.y
d.z = -l*a.z + m * b.z + n * c.z

This system of equations is solved to get m and n using determinants.

If m and n are both between 0 and 1 then the ray hits your rectangle


I hope this helps a bit and I calculated everything correctly.

[edited by - Roland on April 25, 2003 10:34:47 AM]
Butter
Butter
Thanks for you help.

I have chosen to use the following method:
I get the screen coords. of the raster position of the text using gluProject. I then use these and the font height, font width, and string length to calculate the bounding rectangle in screen coords. Then I compare the click screen coords with this bounding box. I loop through all labels and perform this check. The first one hit is the selection.

I''m also planning to use this method to select Points. The bounding box will be generated based on the particular points GL_POINT_SIZE.

See any problems with this method? How bad is gluProject performance wise?

Thanks

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.