swordfish 276 Report post Posted October 21, 2006 (Note: I am using my own equivalent of the glu library for portability reasons; the function is pretty much exactly the same) I am confused what the purpose of the "WinZ" parameter to gluUnProject(WinXYZ,...,ObjXYZ&,...) is? As far as I know, the WinZ is supposed to be the distance I want the 'unprojected' world-space point (ObjXYZ) to be from the camera near plane, in "camera space" [is that the right terminology?] (0.0 = near, 1.0 = far). With the camera facing +Z from Z=0, with a frustum near-far of 0.1-5000.0, I pass a WinXYZ with WinZ as 1.0. The returned ObjXYZ point is around the far-plane at Z=~5000.0 (the result seems to be slightly inaccurate - I'll assume that's normal behavior for now). When I do WinZ=0.0, the returned ObjXYZ point is on the near-plane at Z=~0.1. Everything seems normal so far. But when I pass a WinXYZ with WinZ=0.5, the returned ObjXYZ remains on the near-plane at Z=~0.1, instead of what I wanted: Z=~2500.0. Anything other than WinZ=1.0 results in the ObjXYZ remaining on the near-plane. Q) Is this supposed to happen? Q) Is the slight inaccuracy in gluUnProject() normal? Thanks. My gluUnProject() equivalent, just in case there's an error I may have overlooked: The difference is that the inverse composed projection and modelview matrices are precomputed outside of the function bool UnProjectVector(Vector3f& rkVec, Matrix4f& rkInvComposedMatrix, float afViewport[4]) { Vector4f kIn; Vector4f kOut; kIn[0] = rkVec[0]; kIn[1] = rkVec[1]; kIn[2] = rkVec[2]; kIn[3] = 1.0f; kIn[0] = (kIn[0] - afViewport[0]) / afViewport[2]; kIn[1] = (kIn[1] - afViewport[1]) / afViewport[3]; kIn[0] = kIn[0]*2.0f-1.0f; kIn[1] = kIn[1]*2.0f-1.0f; kIn[2] = kIn[2]*2.0f-1.0f; kOut = rkInvComposedMatrix*kIn; if(kOut[3]==0.0) return false; kOut[0] /= kOut[3]; kOut[1] /= kOut[3]; kOut[2] /= kOut[3]; rkVec = Vector3f(kOut[0],kOut[1],kOut[2]); return true; } 0 Share this post Link to post Share on other sites
Zipster 2377 Report post Posted October 21, 2006 The reason is because the Z-axis transformation is non-linear, and your near plane value is extremely bad. A good near-to-far value ratio range is about 0.001-0.002, while your ratio is .00002! If you have a graphing calculator (or any graphing software), graph the function (-FN/(F-N))(1/x) + (F/(F-N)), which is the projection transformation for the Z-axis, with N=0.1 and F=5000. Choose your viewing window to be x=[N,F] and y=[0,1]. You'll see that the graph is almost vertical around the near plane, and about 90% of your precision is between 0.1 and 1. So when you do the reverse transformation, WinZ is the y value in this graph, and you're determining the x value. Again, you can see that almost the entire y range between 0 and 1 is spanned within the first couple of units of x.Now let N=10 and F=10000 (N/F = 0.001). You'll notice that the graph rises much slower and that there's a smooth rounded curve more reminiscent of the inverse-linear graph 1/x we're used to. As far as testing your function, an N/F of about 0.5 will give you a very good mapping. While you'd never actually use that ratio in a real application, it gives you something almost linear that's easy to test. 0 Share this post Link to post Share on other sites
swordfish 276 Report post Posted October 21, 2006 @Zipster: are you saying the the near/far ratio will adversely affect the outcome of the ObjXYZ?I changed my near/far to 1.0 and 1000.0f, and I just noticed something new. If I pass WinZ as 1.0, I get the ObjXYZ on the far plane. If I pass WinZ as 0.0, I get the ObjXYZ on the near plane. If I pass WinZ as 0.5, I don't get an ObjXYZ half-way between the near and far planes, as I'd expect it to. Instead, as WinZ goes from 0.5 to 1.0, the ObjXYZ depth increase exponentially. A WinZ of 0.999 seems to return what I'd expect a WinZ of 0.5 to return ("half-way"). Am I missing something?[Edited by - swordfish on October 21, 2006 1:50:59 PM] 0 Share this post Link to post Share on other sites
Zipster 2377 Report post Posted October 21, 2006 It's not increasing exponentially, it's increasingly inverse-linearly, according to the equation I posted before. It's not an "adverse" effect, it's just the way the transformation works. I definitely recommend taking a look at the graph of that function. It's guaranteed to answer all your questions [smile] 0 Share this post Link to post Share on other sites
swordfish 276 Report post Posted October 23, 2006 Okay, I see what you mean by 'inverse linear'. I was on the right track at first, but I forgot to invert my Y screen coord, which caused a domino effect of confusion.So in conclusion, WinZ is 1.0/Near. And don't forget to invert your Y-coord (1-WinY).[EDIT]Wrong once again. I did some more research (sorry, I'm not good with graphing) and found this: z = (1/Zn - 1/Z) / (1/Zn - 1/Zf)I can see where many people would get confused here.There is a difference between "Screen Space Z" and "World Space Z".WinZ = (1.0f/fNear-1.0f/fDistance)/(1.0f/fNear-1.0f/fFar)Where fNear/fFar are the near/far plane distances, and fDistance is the distance you want the unprojected point to be from the camera.[Edited by - swordfish on October 26, 2006 12:23:25 PM] 0 Share this post Link to post Share on other sites