|
Title: Projecting 2D screen-space coords to 3D space [finding a ray] Post by: kamac on November 05, 2013, 06:20:28 AM Hey.
I couldn't find proper answer in them webs (Everybody suggest using math libs / etc. for these kind of things), so I'd like to ask here. Assuming I've: -View width, height -2D click position (coords range from 0 to view_width or view_height for Y) -View matrix -Projection matrix How do I get: -Ray origin (I suppose I could just put camera XYZ position here) -Ray direction (I suppose that would be a normalized vector which "begins" in origin) Could somebody provide me explanation? Title: Re: Projecting 2D screen-space coords to 3D space [finding a ray] Post by: soryy708 on November 05, 2013, 06:38:22 AM You know that the "camera" is a frustum (http://techpubs.sgi.com/library/dynaweb_docs/0630/SGI_Developer/books/Perf_PG/sgi_html/figures/04.3.frustum.gif), right?
Well you have the "eyepoint" (tip of the frustum). You need math to find out in which vector do you need to send a ray from tip for it to pass through the point generated from the click X/Y co-ordinates. Title: Re: Projecting 2D screen-space coords to 3D space [finding a ray] Post by: kamac on November 05, 2013, 06:48:22 AM Quote You know that the "camera" is a frustum, right? Well you have the "eyepoint" (tip of the frustum). Well, yes. That's why I wrote this: Quote -Ray origin (I suppose I could just put camera XYZ position here) Quote You need math to find out in which vector do you need to send a ray from tip for it to pass through the point generated from the click X/Y co-ordinates. That's the point of my question. I don't know how to do just that. I read that one could multiply screen-space coords by inverted projection, then multiply *something* by inverted view matrix - I don't know the details. Title: Re: Projecting 2D screen-space coords to 3D space [finding a ray] Post by: rundown on November 05, 2013, 08:00:48 AM If the game is a topdown game you could do this easy with trigoniometrics.
Title: Re: Projecting 2D screen-space coords to 3D space [finding a ray] Post by: wbahnassi on November 05, 2013, 08:06:09 AM Ok, here is some explanation:
First, you have to know that there is missing information in the 2D coordinate (the z coordinate obviously :durr:). So you must think about how to restore this value. Under your context, you want a ray shooting from the screen pixel and into the scene. For common 2D picking, you can assume that the depth of the pixel is 0 (falls on the near camera plane). So now you have a clean 3D coordinate that can be fed into the inverted view-projection matrix. Second, screen coordinates are not what you get when you transform a 3D coordinate by your view/projection matrix. Hence, you cannot feed a screen coordinate into the inverted view/projection matrix and expect a correct result. The output of view/projection transformation is in "clip space", which goes [-1,1] with Y+ going up not down. This means you have to convert your screen coordinate into this "clip space" and _then_ feed the value to the inverted view/projection matrix. This will give you back a 3D coordinate in world space. And now to the code. This is the Unproject function from the DSK3D engine (my engine): Code: struct VIEWPORT { UINT16 uLeft,uTop,uRight,uBottom; float fMinZ,fMaxZ; UINT16 Width(void) const; UINT16 Height(void) const; float Depth(void) const; DSK::VEC3 Unproject(const DSK::VEC3& vScreenPos,const DSK::MAT44& matXViewProjInv) const; }; VEC3 VIEWPORT::Unproject(const VEC3& vScreenPos,const MAT44& matXViewProjInv) const { return matXViewProjInv.XFormProjective(VEC3( (vScreenPos.x-uLeft) / Width() * 2.0f - 1.0f, -((vScreenPos.y-uTop) / Height() * 2.0f - 1.0f), (vScreenPos.z-fMinZ) / Depth())); } You can call it like so: Code: // Replace 640,480 by any screen coordinate you like VEC3 vRayPos1 = viewport.Unproject(VEC3(640,480,0), matViewProjInverted); VEC3 vRayPos2 = viewport.Unproject(VEC3(640,480,1), matViewProjInverted); VEC3 vRayDir = (vRayPos1-vRayPos2).Normalize(); // vRayPos1 is the origin, and vRayDir is the direction The function MAT44::XFormProjective() does a regular transformation of a (vector3,1) which results in a vector4, then it returns the xyz divided by the w as a vector3. This should get you going :) Title: Re: Projecting 2D screen-space coords to 3D space [finding a ray] Post by: kamac on November 05, 2013, 10:32:50 AM In the end, I found the solution following this guys' explanation on stackoverflow:
http://stackoverflow.com/questions/19485046/2d-screen-coordinate-to-3d-position-directx-9-box-select :durr: |