Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!asuvax!enuxha!hollasch From: hollasch@enuxha.eas.asu.edu (Steve Hollasch) Newsgroups: comp.graphics Subject: Projecting from 3D to 2D Summary: How-to article for beginners Message-ID: <3608@enuxha.eas.asu.edu> Date: 20 Jun 91 06:44:19 GMT Reply-To: hollasch@enuxha.eas.asu.edu.UUCP (Steve Hollasch) Organization: Arizona State University Lines: 321 I decided a while back to draw up a simple description of the process of creating 3D images and finally got around to it tonight. This is for beginners who want to know about this process. Also, the next time someone posts to comp.graphics for this information, we'll have a file we can send off! By the way, if you're familiar with the process of projecting from 3D to 2D, I'd recommend that you look over the method I use to convert from 3D world coordinates to 3D eye coordinates. Most folks use rotation matrices (bleeech!), but the method I use is _much_ cleaner. This method is presented in the paper by Thomas A. Foley and Gregory Nielson referenced at the end of this article. ---------------------------------------------------------------------------- Projecting Points From 3D To 2D Steve Hollasch 19 June, 1991 ------- Introduction I've decided to whip up this article in response to the many queries about the process of creating 3D graphics. There are a number of books that cover this subject, but this article should be useful for those folks that want something online. This document presents the series of steps needed to project a point in three-space to a point in two-space. In other words, how to create a two-dimensional image from a three dimensional scene. There are four parts to this problem: (1) Providing the 3D coordinates of the point and the 3D viewing parameters. (2) Converting the point's world coordinates to eye coordinates. (3) Projecting the 3D point to 2D normalized coordinates. (4) Mapping the 2D normalized coordinates to the display window. In step one, we specify how we're going to look at the 3D scene. Then we convert the 3D coordinates of each point to ``eye coordinates''. This step is necessary for step three, where we project the point to the normalized coordinate rectangle, i.e. the [-1,+1] x [-1,+1] rectangle. Finally, we then map the normalized coordinate rectangle to our display window (e.g. 512 pixels by 1024 pixels). ------- Viewing Parameters The first thing we need to establish is how we're looking at the 3D scene. One obvious thing we need to know is the location we're looking from, called the viewpoint or from-point. This location specifies where our ``eye'' is located in 3D. The next thing we need to establish is the line of sight (where we're looking). We can accomplish this by either specifying a line-of- sight vector, or by specifying a point of interest in the scene. The point-of-interest method has several advantages. One advantage is that the person setting up the scene usually has something in mind to look at, rather than a particular direction of sight. It also has the advantage that you can ``tie'' this point to a moving object, so we can easily track the object as it moves through space. This point of interest is called the to-point. Now we need to establish an orientation of our view. Most pictures are oriented so that the ground is at the bottom of the image and the sky is at the top of the image. However, not all scenes have ground or sky, so we need to specify which direction is up. To do this, we specify a vector called the up-vector. If the up vector were included in the scene, it would always be rendered pointing straight up in the final image. Note that the up-vector need not be perpendicular to the line of sight (we'll ``straighten'' it later), but it must not be parallel to the line of sight (think about it). We also need to specify the amount of perspective, or ``zoom'', that the image will have. This is given by the viewing angle. Think of it this way. The rectangle we'll be projecting onto is perpendicular to the line-of-sight, in front of the from-point. You can think of this rectangle as the ``window'' we'll be looking through. If you connect each corner of the viewing rectangle to the from-point, you'll get a rectangular cone -- this is known as the viewing frustum. The angle of the tip of the viewing frustum is the viewing angle. A slender cone has a small viewing angle, and a fat cone has a large viewing angle. Note that there are two viewing angles, one horizontal and one vertical. For simplicity, I'll assume that these are the same. However, if your display device does not have a 1:1 aspect ratio, you'll need to determine what the vertical viewing angle is in terms of the horizontal viewing angle and the aspect ratio. This viewing angle must reside in the range of 0 to pi, exclusive. Small viewing angles yield a telephoto effect, and large viewing angles yield a wide-angle effect. Note that if you change to a large viewing angle, you'll need to move the from-point closer to keep the object large in the image. So, these are the 3D viewing parameters we need: (1) From-Point [3D Point]: Where we're looking from. (2) To-Point [3D Point]: Where we're looking to. (3) Up-Vector [3D Vector]: Tells us where ``up'' is. (4) Viewing Angle [Degrees]: Telephoto vs. wide-angle. ------- Converting World Coordinates to Eye Coordinates The first step in projecting the 3D point to the normalized coordinate rectangle is to convert the 3D ``world'' coordinates to 3D ``eye'' coordinates. This makes the projection much more simple. In the eye-coordinate system, the from-point is located at the origin, the line-of-sight is the Z axis, the up vector is the Y axis, and the X axis is perpendicular to the Y and Z axes. It turns out that there's a relatively easy way to do this. Most other techniques you'll see in textbooks involves the three different rotations comprised of three 3x3 matrix multiplies -- very messy. This method involves a single 3x3 matrix multiplication and no trigonometric functions. Let C be the unit vector along the line-of-sight, B be the vector perpendicular to C that points ``up'', and A be orthogonal to the vectors B and C. What we'd like to see is a 3x3 transformation matrix such that [Ax Ay Az] T = [ 1 0 0 ], [Bx By Bz] T = [ 0 1 0 ], and [Cx Cy Cz] T = [ 0 0 1 ]. In other words, the unit vector perpendicular to the line-of-sight and up-vector should map to the X axis, the unit perpendicular-up vector should map to the eye-coordinate Y axis, and the unit vector along the line-of-sight should map to the eye-coordinate Z axis. These three equations can be combined in the form +- -+ +- -+ | Ax Ay Az | | 1 0 0 | | Bx By Bz | T = | 0 1 0 | | Cx Cy Cz | | 0 0 1 | +- -+ +- -+ So how do we solve for the transformation matrix T? Well, notice that because of the way we've constructed the vectors A, B and C, the matrix composed of the A, B and C row vectors is an orthogonal matrix. Orthogonal matrices have the wonderful property that their inverse is equal to their transpose. So, simplifying, we get +- -+ +- -+ +- -+ +- -+ | Ax Bx Cx | | Ax Ay Az | | Ax Bx Cx | | 1 0 0 | | Ay By Cy | | Bx By Bz | T = | Ay By Cy | | 0 1 0 | | Az Bz Cz | | Cx Cy Cz | | Az Bz Cz | | 0 0 1 | +- -+ +- -+ +- -+ +- -+ which simplifies to +- -+ | Ax Bx Cx | T = | Ay By Cy | | Az Bz Cz | +- -+ Note that before applying this transformation, we need to translate the world-coordinate origin to the eye-coordinate origin by subtracting the from-point. All that's left for this transformation is to figure out the A, B and C vectors. These are given by To - From C = --------------- || To - From || Up X C A = -------------- || Up X C || B = C X A These vectors are all unit vectors (B is a unit vector because A and C are normalized). So, the final equation is +- -+ | Ax Bx Cx | [Ex Ey Ez] = [(Px - Fx) (Py - Fy) (Pz - Fz) ] | Ay By Cy | | Az Bz Cz | +- -+ , where E is the eye-coordinate point, P is the world-coordinate point, F is the from-point, and the A, B and C vectors are computed above. ------- Projecting from 3D Eye Coordinates to 2D Normalized Coordinates Now that we have eye-coordinates (Ex, Ey, Ez) of the data point, we can project the point to the normalized viewing rectangle. To calculate the perspective projection of point P', we need to project the point to the viewplane and then to normalize the values so that points on the Z axis are projected to X (or Y) = 0, and so that the values of X (or Y) range from -1.0 to +1.0. /|\ X _/| ____. E | _/ | ___/ | _/ | ___/ | _/ __./ | _/ ___/ | T | /___/ | \ +------------+------------------------------------------ \_ V/2 | /|\ / Z \_ | | \_ | tan(V/2) \_ | | (V is the viewing angle) \_ | | \| _\|/_ |/__________\| |\ 1 /| Ex Tx The X axis value from this figure is calculated by noting that -- = --. Ez Tz We can let Tz = 1 if the viewing angle is still preserved. Thus, Ex Tx = --. To normalize Tx, note that the maximum possible value of Tx on Ez Tx the viewing plane occurs at -- = tan(V/2). The equations for the Y axis Tz are similar. Thus, the equations for the normalized perspective projection T are given by Ex Ey Tx = ----------- and Ty = ----------- Ez tan(V/2) Ez tan(V/2) where E is the eye-coordinate point of P, T is the normalize rectangle coordinate point, and V is the viewing angle. Again note that we're assuming the viewport is square (and the aspect ratio is 1:1). If this is not the case, then Ty or Tx would be scaled to account for this. ------- Mapping From The Normalized Viewport to The Display Window Now that we have the coordinates in the range of [-1,+1] x [-1,+1], we need to map them to the display window. Let the center of the display window be Cx and Cy, and let the length of the display window edges be Lx and Ly (both of these units are in pixels, and the device origin [0,0] is in the lower left corner). Then the device coordinates (Dx, Dy) of the point are given by the following equations: Lx Ly Dx = Cx + -- Tx and Dy = Cy + -- Ty . 2 2 The device coordinates Dx and Dy will be in pixels. ------- Putting It All Together Here's a brief recap of what you need to do to project the point P to the display window: (1) Calculate the vectors A, B and C to form the transformation matrix. (2) Use the matrix to convert the point P to the eye-coordinate point E. (3) Project the eye-coordinate point E to the [-1,+1] x [-1,+1] normalized coordinate rectangle. (4) Map this rectangle to the display window in screen coordinates (usually pixels). ------- References Thomas A. Foley, Gregory M. Nielson, ``Practical Techniques for Producing 3D Grahpical Images,'' VMEbus Systems, Nov-Dec 1987, pp. 65-73. Donald Hearn, M. Pauline Baker, _Computer_Graphics_, Prentice-Hall, Inc., 1986. Francis S. Hill, Jr., _Computer_Graphics_, Macmillan Publishing Co., New York NY, 1990. David F. Rogers, _Procedural_Elements_For_Computer_Graphics_, McGraw-Hill, Inc., 1985. ______________________________________________________________________________ Steve Hollasch / Arizona State University (Tempe, Arizona) hollasch@enuxha.eas.asu.edu / uunet!mimsy!oddjob!noao!asuvax!enuxha!hollasch