Menu

RENDERING PROCESS:

MISCELLANEOUS:


Mail me ! Go home

Step III: The Projection Plane

INTRODUCTION:
The projection plane (or view plane, or viewing plane) is a flat surface in front of the camera (or player if you prefer) where images are projected. The plane usually has dimensions equal to that of the physical screen, but it can be any size. The camera is situated at a certain distance behind the plane, which is called it's focal-distance.

The further you look into the distance, the wider your horizon, and thus you can see more objects (although they'll be smaller, obviously). This area can can be represented as a pyramid, imaginatively called the projection pyramid. To make things clearer, take a look at the diagram below:
images/fig6.jpg
fig6: The projection pyramid

The above shows a plane that has dimensions of 320x200 units (for convenience, 1 unit will be equal to 1 pixel) which coincides with the dimensions of a commonly used VGA mode. The angle marked alpha is the horizontal field-of-view (or FOV), which determines how much can be seen. There is no need for a vertical FOV because everything is scaled according to the horizontal FOV.

Humans have a FOV (both horizontal and vertical) of about 90°, which does not look right when used for a raycaster. Through trial-and-error, I've found that the best-looking FOV to use is 60°. So, the angle alpha, above, will have a value of 60° and the rest can be determined by using simple trigonometry.

FINDING THE FOCAL-DISTANCE:
The focal-distance is used for scaling, and only needs to be calculated every time the FOV or plane width changes, which means that once calculated, it can be stored in a variable until the FOV or plane-width is modified again. The focal-distance value is used extensively by the engine, so it doesn't pay to recalculate everytime it's needed; a memory access is a lot quicker.

Here is a 2D drawing of the overhead of the view pyramid. It can be split into two identical right-angled triangles, as shown in fig7:
images/fig7.jpg
fig7: 2D overhead view of the projection pyramid

The length we need to find (the focal-distance) is the one labelled dist. The width is the width of the projection plane, and alpha is it's FOV. Taking away the triangle that we're not working on, we are left with this:
images/fig8.jpg
fig8: The triangle for finding the focal-distance

All values are divided by 2 (except dist, obviously) because the two parts of the full view-triangle were identical. So, to find a value for dist, we first decide whether to use sine, cosine or tangent; Pythagoras' theorem can't be used because we only know one length, which is width / 2.

We use tangent because we want to find adj (which equates to dist in our calculations), and we only know opp (which is width / 2); we don't know hyp, which would be needed for sine and cosine. Here's the equation for finding dist, and where it's derived from:

A few variables:                             |
        alpha = fov   / 2,                   | Using these names makes
        opp   = width / 2,                   | everything clearer/shorter
        adj   = dist                         |

We start with:
                     opp                     | This is the standard
        TAN(alpha) = ---                     | equation for tangent
                     adj                     |

Canceling out 'adj' (multiplying both sides by it), we get:
        TAN(alpha) * adj = opp               | Multiply both sides by 'adj'

But we already know 'opp', so make 'adj' the subject (divide by TAN(alpha)):
	                      opp            | The final equation with
        adj              = ----------        | 'adj' as it's subject
                           TAN(alpha)        |

So there we have it, we've found the formula that calculates adj which is 'dist', aka the focal-distance. Now we simply have to plug our values into it, like this:

We start with the core equation:
               width   / 2
        dist = ------------
               TAN(FOV / 2)

Now we substitute in the variables' values (from the above diagrams):
               320 / 2    = 160
        dist = ----------------
               TAN(60 / 2 = 30)
             = 277.128 (or something close to it, at least)

        dist = 277 units

At this stage we've determined that the projection plane is 277 units from the camera when using a FOV of 60° and a width of 320 units.

We also need to calculate the angle between subsequent rays, which is just a term to make me sound clever :) Not really, but all it means is how many degrees there are in each column of the projection plane, recalling that a ray needs to be cast for every column of the projection plane. Since each column is equal to 1 unit, then it's easy. If you haven't worked it out by now (or haven't understood what the hell I'm on about), then here's how to do it:

                                      FOV
        degrees_per_column = ----------------------
                             projection_plane_width

And using the values from above, that is:

                             60
        degrees_per_column = ---
                             320

                           = 0.1875

Since I said that 1 unit would be 1 pixel in this documentation, and also that the projection plane would be the same size as the physical screen, that means that every pixel of every row is worth 0.1875°; a full row would be the FOV (60°). Store this value in a variable also, as it's used quite frequently, and a divide is by far the most expensive arithmetic operation a computer can do.

CONCLUSION:
In case you're interested, or perhaps lazy, here's a C code listing of a function that can calculate the focal-distance and angle between subsequent rays. It's not optimized in any way, and it uses floating point variables (whereas you may wish to use fixed-point if you've got an old machine; more on that later).

There, the first piece of mathematics, and the first piece of code; you can't say that it wasn't easy, can you ? Anyway, the next step will be the part where trigonometry is used the most in the engine. It takes you through finding walls in the raycasting environment [grin].


NEXT PAGE PREVIOUS PAGE


Last updated: 02/11/00
Copyright © Peter Restall, 1998-2000
Best viewed with Netscape Navigator in a resolution of 1600x1200