The math I’m using to compute a 3D vector based on a mouse click works fine, but the fact that it works is bothering me – specifically, I am scaling the field of view, expressed on the vertical axis by the aspect ratio for the horizontal axis, instead of computing a new ratio based on the field of view for the horizontal axis – the reason this bothers me is that I am linearly scaling the field of view, whereas recomputing the fov tangent for the horizontal axis is not linear – so I wonder if I’ve got a slightly abberant lens in my camera at the end of the day.
Here’s the code, which works fine (note that the FOV is expressed for the horizontal axis and D3D wants it for the vertical axis)
double mouseX = ((((double) hitPt.x) / (double) vport.cx) - 0.5) * 2.0;
double mouseY = ((1.0 - (((double) hitPt.y) / (double) vport.cy)) - 0.5) * 2.0;
double tfy = tan((fov/aspr) * 0.5);
double tfx = tfy * aspr;
SFMatrix4 CM1;
this->m_renderSurface->GetRawCameraMatrix(CM1);
CM1.Invert();
origin = CM1 * SFVec3f((nearp * tfx) * mouseX,(nearp * tfy) * mouseY,nearp);
dest = CM1 * SFVec3f((farp * tfx) * mouseX,(farp * tfy) * mouseY,farp);
I’ve isolated the line that is offending my sensibilities (tfx = tfy * aspr) – I would rather do
tfx = tan(fov) * 0.5;
but that does not work – there’s an error that increases as it moves away from the center
I know that this is the way that D3D does things and I’m just going to have to live with it – what I’m curious about is which path is actually right (as much as anything can be right in the attempt to shove linear algebra through a discrete mesh), and why
I agree that this is an aspect of projection that is unintuitive at first.
The field of view of your eyes is essentially projected on a sphere. As a result an object that subtends a certain angle appears to have the same size regardless of whether you are looking straight at it or seeing it in your peripheral vision. The angle difference between two edges of an object is what defines the size, and therefore the angle to an object is a good way to define its position in the field of view.
When projecting onto a flat surface, the rules are a bit different. Look at this picture:
The position of each object on the screen is not determined by the angle to that object. Instead, we use similar triangles: