Re: [Plib-users] Window (x,y) to world coordinates
Brought to you by:
sjbaker
From: Steve B. <sjb...@ai...> - 2001-12-20 04:10:32
|
Ask For Joy wrote: > I have a PLIB application in which my camera is facing down along the Z axis to > look at a grid on the XY plane. I can move the camera up and down along the Z > axis to effectively 'zoom' my view of the plane. (Technically, that's not "zooming" - you have to change the camera's field of view to make it zoom). > I can also move the camera > along the XY axis, but in all cases I am looking down square upon the XY axis . That's probably because SG & SSG use a 'Z-is-up' coordinate system so the default camera is looking along the Y axis towards Y==+infinity. If you made your XY grid in a 3D modelling program then it's probably built using Y-is-up and our model loaders will have switched the coordinates around for you so it's now an XZ grid. Now, it's a vertical wall and we are staring straight at it. When you move the camera in Z, you are getting higher in altitude - which I think explains what you are seeing. Of course this is all blown away as an explanation if you typed the grid into your C++ code and stuffed the coordinates directly into SSG. (Yes, I know that OpenGL uses Y-is-up - but I come from a flight simulation background and we've always used Z-is-up. When I wrote SSG, I didn't really intend for anyone else to ever use it - so I wrote it for *MY* personal convenience...it doesn't matter at all in terms of functionality - but it can be a little confusing for beginners and people who use Y-is-up routinely.) > What I am looking for is a way to translate window coordinates obtained from the > mouse to world coordinates, taking into account the window dimensions and > current camera position. Well, you can't do that for an arbitary setup - because there are an infinite number of world coordinates that lie in a line from your eye through the mouse position and out into the world. However, if you just want to know where it hit your XY plane (or any other specific plane for that matter) then you need to do this: Figure out where the 'camera' is in your world. Imagine that this is really where your eye is. Imagine the screen sitting in your scene at an appropriate distance and direction from your eye for the field of view that you selected. Imagine the mouse cursor stuck onto that little rectangle. Draw a line from the eye, through the tip of the mouse out into the scene. Figure out where that line intersects your infinite plane...that's the coordinate you need. The routine: sgIsectInfLinePlane ( sgVec3 dst, sgVec3 l_org, sgVec3 l_vec, sgVec4 plane ) ; ...computes the intersection of an infinite line with an infinite plane. So 'dst' will be populated with the results. 'l_org' is the origin of your line (which in this case is the position of the camera (your eye) in the scene. 'l_vec' is a unit vector pointing in the direction of the line. This is going to be defined by the mouse position rotated by the camera rotation. 'plane' is the plane equation of your infinite plane (you can form the plane equation directly if you know what you are doing - if not, pass three points from the plane into sgMakePlane and it'll figure out the plane equation for you). The hardest part of this is getting the 'l_vec' thing right. The easy way is to create a 3D point that represents the mouse coordinate... so if the mouse is at: ( mx, my ) then in 3D, it's at ( mx, screendist, my ) (remembering that Z-is-up in PLIB - and assuming your mouse coordinates are (0,0) in the center of the screen with Y getting bigger towards the top of the screen and X getting bigger to the right). The 'screendist' thing is the distance of the screen from your eye. You have to figure that out using the field of view angle and some simple trig.. screendist = (screen_width/2) / tan ( horizontal_fov / 2 ) (Notice that the 'screen_width' term has to be in the same units as your mouse coordinates). *PHEW* nearly there! Now you have to transform the 3D mouse coordinate by the current camera (modelview) matrix to get it's position in World coordinates. Now subtract the eyepoint position in the world to get a vector - normalize it to get a unit vector. Now you have everything you need to call sgIsectInfLinePlane. One slight 'gotcha' is that when you are flying over your infinite 'ground' plane, you might point the mouse up into the 'sky' where it doesn't hit the plane at all...well, actually it does because sgIsectInfLinePlane intersects an INFINITE line - it's infinite in both directions so what you'll actually get under these circumstances is a 'hit' on the 'ground' somewhere behind the camera. What you want to do under these circumstances depends on your application. There are SG routines for all of those separate operations - but no single function to do the entire thing (that I'm aware of). If some kind soul were to write such a thing, it would be cool to put it into the SSG camera class. > Is there an easy formula or matrix operation in PLIB > that will allow me to do this? I tried playing around with the ortho matrix, > but my experimentation didn't get me very far. Easy is a relative term... In a program like PrettyPoly (http://prettypoly.sf.net), we do this by intersecting a ray from the eye out through the mouse cursor and figuring out which polygon it struck. Then we can find the plane equation of that polygon and figure out where it was hit. That removes the limitation of only hitting a single plane - but it's *MUCH* more complicated. We actually use OpenGL's 'pick' feature to find out what we clicked the mouse on - there is special support for that in SSG - but since PPE is the one thing it was written for, the documentation is pretty much absent. > BTW, PLIB is wonderful. Its very gradual learning curve and intutitive > interface is the main reason why I switched back from Direct3D to OpenGL for my > application. <blush> ----------------------------- Steve Baker ------------------------------- Mail : <sjb...@ai...> WorkMail: <sj...@li...> URLs : http://www.sjbaker.org http://plib.sf.net http://tuxaqfh.sf.net http://tuxkart.sf.net http://prettypoly.sf.net http://freeglut.sf.net http://toobular.sf.net http://lodestone.sf.net |