I just played a bit more. I put camera(0,0,10,0,0,0,0,1,0)
and perspective(40,HEIGHT/WIDTH)
(or was it WIDTH/HEIGHT
- whatever the standard was). I then drew a basic object on the screen and gave myself a parameter to vary its z
-coordinate. As expected, when the z
-coordinate gets to about 9
then it reaches the “front” of the screen and gets clipped. But the back is a long way off! In fact, I suspect that there is no back. I got up to z = -1000
and my object was still there (albeit as a single pixel). This semi-infinite ray gets squashed into the interval [-1,1]
and so the inversion formula is quite bad.
I’ve yet to find any code for glUnProject
that does anything any better than inverting the matrix. I had one idea which would be that since we’re using homogeneous coordinates, it’s always okay to work with a multiple of the matrix or the vector. So whenever there’s an operation which can introduce inaccuracies and which involves multiplication or division then it might be possible to avoid it. For example, instead of inverting the matrix you can use the cofactor matrix. But I don’t think that these fix things too well.
There are two steps needed:
- Convert the touch to a ray for answering “Was this object touched?”
- Convert the touch to a point at a specific
z
-level as specified by the object that claimed the touch so that it can deal with it in its own frame of reference.
For the first, we need two points and two that can be determined accurately. For that, I think we need to be near the front of the screen, but not too near. Good values are going to be ones that give a solid value for the fourth coordinate (since we end up dividing by that). I wonder if this is predictable.
For the second, we use the routine above with the specific z
-value and have to live with the inaccuracy. Hopefully the object will be nicely in the frustum and so the inaccuracy won’t be too bad.