The Wikipedia article also confused me when I read it some time ago. Here is my attempt to explain it differently:
Situation
Let's simplify the situation. We have:
- Our projected point D (x, y, z) is what you call relativePositionX | Y | Z
- Image plane w * h
- A viewing polygon α
... and we want:
- B coordinates in the image plane (let's call them X and Y )
Scheme for X-screen coordinates:

E is the position of our “eye” in this configuration, which I have chosen as a source for simplification.
The focal length f can be estimated, knowing that:
A bit of geometry
You can see in the picture that the triangles ECD and EBM are similar , so use the Side Branch Theorem , we get:
MB / CD = EM / EC <=> X / x = f / z (2)
When using (1) and (2) we now have:
X = (x / z) * ( (w / 2) / tan(α) )
If we return to the notation used in the Wikipedia article, our equation is equivalent to:
You may notice that we are missing the multiplication by s_x / r_x . This is due to the fact that in our case the "display size" and the "recording surface" are the same , therefore s_x / r_x = 1 .
Note. The same reasoning for Y.
Practical use
Some notes:
- Commonly used is α = 45deg, which means
tan(α) = 1 . That is why this term does not appear in many implementations. If you want to keep the ratio of the displayed elements, keep f constant for both X and Y , that is, instead of calculating:
X = (x / z) * ( (w / 2) / tan(α) ) and Y = (y / z) * ( (h / 2) / tan(α) )
... do:
X = (x / z) * ( (min(w,h) / 2) / tan(α) ) and Y = (y / z) * ( (min(w,h) / 2) / tan(α) )
Note: when I said that the “screen size” and the “recording” of the “surface” are the same “, it wasn’t quite so, and min work here to compensate for this approximation by adapting the square surface r to the potentially rectangular surface s.
Note 2: Instead of using min (w, h) / 2, Appunta uses screenRatio= (getWidth()+getHeight())/2 , as you noticed. Both solutions retain the elements of correlation. The focal, and therefore the angle of view, will simply be slightly different, depending on the screen’s own ratio. You can use any function, define f.
As you can see in the picture above, the screen coordinates here are defined between [-w / 2; w / 2] for X and [-h / 2; h / 2] for Y, but you probably want [0; w] and [0; h]. X += w/2 and Y += h/2 - the problem is solved.
Conclusion
I hope this answers your questions. I will stay close if he needs publications.
Bye!
<Warning about self-promotion> I actually did some time ago an article about 3D projection and rendering. Implementation in Javascript, but it needs to be pretty easy to translate.
source share