Finding depth from a 2d screen point

I am writing a 3d design/viewing program in visual basic and I am trying to create a function where the user can draw lines on a plane (right now i just have y=0) by clicking on the screen. I need to know how to transform the 2d point (x,0) to a 3d point. another related problem is the mouse’s coordinates (x,y) are not the same as the camera or world space coordinates.

also…vb’s line drawing function is too slow for my application…is there a high performance line drawing function available?

Hum, to tranform a (x,y) coordinate to 3d is easy: (x,y,z) with z = any fixed value you find suitable, such as 0.
Your description is not very precise, are you using a perspective view or a plain 2D one ?

>> is there a high performance line drawing function available ?
Yes, use OpenGL ! :stuck_out_tongue:

Well…the program im making is a 3d design program. Basically, I have a 3d plane (grid) that the user will create 3d objects by clicking on the screen from a perspective view. So, based on the screen point (x,y) that they click and the camera angles they are rotated on, I was wondering if it was possible to find the depth of the point when y=0 (because they are drawing flat on the grid the way I have it now). It’s pretty much the way other designing programs work.

I’ve never used openGL before…I tried working with directx 8 for a while, but it seemed like i would have to change a lot of things on my program to get it to work right.

Here’s one way to think about it.

First, to get the direction of the selection ray you can use gluUnProject(…) with 0 and 1 for the near and far winz, respectively.

Once you have the 2 end points, create a selection ray from them:

R = unproject(z=1) - unproject(z=0).

Now, given an eye position E in world-space, and our ray direction R, our projected point P will be on the line

P = E + R t, for some t.

To solve for t, we know that t satisfies

dot(E + R t, N) = D,

where N is the plane’s normal, and D is the plane’s distance. So,

t = (D - dot(E,N)) / dot(R,N).

Note that when dot(R,N) = 0, there is no solution, and no intersection with the plane.

Now, we just plug t into the line

P = E + R * (D - dot(E,N)) / dot(R,N).

This will work for both perspective and orthographic views.

For the details of gluUnProject():
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/opengl/glufnc01_3xv8 .asp

what is the plane’s distance D? which plane are you talking about? is it the near plane of the perspective clipping volume?

Hi Sunnymonk,

For any point P on a plane with normal N, dot(P,N) = D. The D is simply the distance to the plane, as measured from the origin along the plane’s normal.

And this was for any plane in 3-space. The UnProject part was added only to create a selection vector to work with in response to mouse movement.

Does this help?

Hi graham,
thanks for your reply! It give me a better idea but just to clear it, to get the world coordinate from the mouse position on screen, i can just use the gluUnproject()?

im trying to interpret a line drawn on screen using the mouse. i want to create a plane from the first point of the line, the last point of the line and the camera in the world. So, do i gluUnproject the first point and last point of the line and then do the normal plane calculation?

Or do i need to carry out the way you find P using D,N and the selection vector in your previous thread?

i really want to thank you for your help!

Sorry, just to add on to my prev post, the first point and the last point of the line drawn will not be on a polygon, it will land somewhere in an empty space. Do you think gluUnproject() will give me what i want?

to get the world coordinate from the mouse position on screen, i can just use the gluUnproject()?
That’s exactly right; that’s really the sole purpose of that function. You want to use the current modelview and projection matrices, along with the current viewport. Remember that the winZ is between 0 and 1. You may also need to flip the winY in order to keep the GL happy. OpenGL likes having the screen origin in the lower-left corner, as opposed to the common Windows origin in the upper-left. To do this flipping, give gluUnProject viewport[3] - 1 - winY instead, where viewport is that retrieved by glGetIntergerv(GL_VIEWPORT, viewport).

So, do i gluUnproject the first point and last point of the line and then do the normal plane calculation?

That sounds reasonable to me. My only concern would be getting the winding order right to orient your plane the way you want, and how you plan to produce the winz’s, but I’m sure you have all that figured out :wink:

Of the original post, you only need 1%, the gluUnproject part. All the other stuff was just a way to intersect a line from the eye position with a plane in the world. It doesn’t sound like you need that bit. It sounds like you should be good to go.

Savvy?

hi graham,

For any point P on a plane with normal N, dot(P,N) = D. The D is simply the distance to the plane, as measured from the origin along the plane’s normal.
this is only true if N is a normalized normal.

Hi GreetingsFromMunich,

Thanks for clearing that up for us :slight_smile:

Hi again,
I tried to use the gluUnproject, and it works fine to find my plane from the first point of line, last point of line and the camera. (refer to my prev post) The plane i am finding is going to intersect my object in the scene.

However, it seems that whenever i rotate my camera using gluLookAt around my object in the world, and then i tried to draw a line on screen, the intersection points seems to go haywire. I suspect that when i rotate my camera, the gluUnproject produce the wrong coordinates. Can anyone help me ??