home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / PCGPEV10.ZIP / PERSPECT.TXT < prev    next >
Text File  |  1994-05-10  |  5KB  |  150 lines

  1.  
  2.                    ┌────────────────────────┐
  3.                    │ Perspective Transforms │
  4.                    └────────────────────────┘
  5.  
  6.         By Andre Yew (andrey@gluttony.ugcs.caltech.edu)
  7.  
  8.  
  9.  
  10.     This is how I learned perspective transforms --- it was
  11. intuitive and understandable to me, so perhaps it'll be to
  12. others as well.  It does require knowledge of matrix math
  13. and homogeneous coordinates.  IMO, if you want to write a
  14. serious renderer, you need to know both.
  15.  
  16.    First, let's look at what we're trying to do:
  17.                S (screen)
  18.                |    * P (y, z)
  19.                |   /|
  20.                |  / |
  21.                | /  |
  22.                |/   |
  23.                * R  |
  24.              / |    |
  25.             /  |    |
  26.            /   |    |
  27.    E (eye)/    |    | W
  28. ---------*-----|----*-------------
  29.          <- d -><-z->
  30.  
  31.    E is the eye, P is the point we're trying to project, and
  32. R is its projected position on the screen S (this is the point
  33. you want to draw on your monitor).  Z goes into the monitor (left-
  34. handed coordinates), with X and Y being the width and height of the
  35. screen.  So let's find where R is:
  36.  
  37.     R = (xs, ys)
  38.  
  39.     Using similar triangles (ERS and EPW)
  40.  
  41.     xs/d = x/(z + d)
  42.     ys/d = y/(z + d)
  43.     (Use similar triangles to determine this)
  44.  
  45.     So,
  46.  
  47.     xs = x*d/(z + d)
  48.     ys = y*d/(z + d)
  49.  
  50.     Express this homogeneously:
  51.  
  52.     R = (xs, ys, zs, ws).
  53.  
  54.     Make xs = x*d
  55.          ys = y*d
  56.          zs = 0 (the screen is a flat plane)
  57.          ws = z + d
  58.  
  59.     and express this as a vector transformed by a matrix:
  60.  
  61.     [x y z 1][ d 0 0 0 ]
  62.              [ 0 d 0 0 ]    =  R
  63.              [ 0 0 0 1 ]
  64.              [ 0 0 0 d ]
  65.  
  66.     The matrix on the right side can be called a perspective transform.
  67. But we aren't done yet.  See the zero in the 3rd column, 3rd row of
  68. the matrix?  Make it a 1 so we retain the z value (perhaps for some
  69. kind of Z-buffer).  Also, this isn't exactly what we want since we'd
  70. also like to have the eye at the origin and we'd like to specify some
  71. kind of field-of-view.  So, let's translate the matrix (we'll call
  72. it M) by -d to move the eye to the origin:
  73.  
  74.     [ 1 0 0  0 ][ d 0 0 0 ]
  75.     [ 0 1 0  0 ][ 0 d 0 0 ]
  76.     [ 0 0 1  0 ][ 0 0 1 1 ]  <--- Remember, we put a 1 in (3,3) to
  77.     [ 0 0 -d 1 ][ 0 0 0 d ]       retain the z part of the vector.
  78.  
  79.     And we get:
  80.  
  81.     [ d 0 0  0 ]
  82.     [ 0 d 0  0 ]
  83.     [ 0 0 1  1 ]
  84.     [ 0 0 -d 0 ]
  85.  
  86.     Now parametrize d by the angle PEW, which is half the field-of-view
  87. (FOV/2).  So we now want to pick a d such that ys = 1 always and we get
  88. a nice relationship:
  89.  
  90.     d = cot( FOV/2 )
  91.  
  92.     Or, to put it another way, using this formula, ys = 1 always.
  93.  
  94.     Replace all the d's in the last perspective matrix and multiply
  95. through by sin's:
  96.  
  97.     [ cos 0   0    0   ]
  98.     [ 0   cos 0    0   ]
  99.     [ 0   0   sin  sin ]
  100.     [ 0   0   -cos 0   ]
  101.  
  102.     With all the trig functions taking FOV/2 as their arguments.
  103. Let's refine this a little further and add near and far Z-clipping
  104. planes.  Look at the lower right 2x2 matrix:
  105.  
  106.    [ sin sin ]
  107.    [-cos 0   ]
  108.  
  109.    and replace the first column by a and b:
  110.  
  111.    [ a sin ]
  112.    [ b 0   ]
  113.    [ b 0   ]
  114.  
  115.    Transform out near and far boundaries represented homogeneously
  116. as (zn, 1), (zf, 1), respectively and we get:
  117.  
  118.    (zn*a + b, zn*sin) and (zf*a + b, zf*sin).
  119.  
  120.    We want the transformed boundaries to map to 0 and 1, respectively,
  121. so divide out the homogeneous parts to get normal coordinates and equate:
  122.  
  123.     (zn*a + b)/(zn*sin) = 0 (near plane)
  124.     (zf*a + b)/(zf*sin) = 1 (far plane)
  125.  
  126.    Now solve for a and b and we get:
  127.  
  128.    a = (zf*sin)/(zf - zn)
  129.      = sin/(1 - zn/zf)
  130.    b = -a*zn
  131.    b = -a*zn
  132.  
  133.    At last we have the familiar looking perspective transform matrix:
  134.  
  135.    [ cos( FOV/2 ) 0                        0            0 ]
  136.    [ 0            cos( FOV/2 )             0            0 ]
  137.    [ 0            0 sin( FOV/2 )/(1 - zn/zf) sin( FOV/2 ) ]
  138.    [ 0            0                    -a*zn            0 ]
  139.  
  140.    There are some pretty neat properties of the matrix.  Perhaps
  141. the most interesting is how it transforms objects that go through
  142. the camera plane, and how coupled with a clipper set up the right
  143. way, it does everything correctly.  What's interesting about this
  144. is how it warps space into something called Moebius space, which
  145. is kind of like a fortune-cookie except the folds pass through
  146. each other to connect the lower folds --- you really have to see
  147. it to understand it.  Try feeding it some vectors that go off to
  148. infinity in various directions (ws = 0) and see where they come
  149. out.
  150.