home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / utilities / utilsf / graphtext / Eddie1 < prev    next >
Encoding:
Internet Message Format  |  1995-06-12  |  5.5 KB

  1. To: A.Pereira@cs.ucl.ac.uk
  2. From: Eddie Edwards <eddie@powerslv.demon.co.uk>
  3. Subject: Fast texture coordinate calculation
  4. Reply-To: eddie@powerslv.demon.co.uk
  5. Date: Mon, 01 May 1995 19:35:04 +0100
  6. Message-ID: <19950501.193504.29@powerslv.demon.co.uk>
  7. Organization: I Inhaled
  8. X-Mailer: Archimedes TTFN Version 0.36
  9.  
  10.  SUMMARY
  11.  =======
  12.  
  13.  This article presents a fast method for calculating texture-map column
  14.  indices when rendering Wolf 3D or DOOM-style walls.  Although the method I
  15.  describe assumes that you are plotting a square texture (e.g. 128x128
  16.  pixels) the method could easily be extended for plotting non-square
  17.  textures.
  18.  
  19.  NOTATION
  20.  ========
  21.  
  22.  (u,v) are coordinates in texture space
  23.  (x,y) are coordinates in screen space
  24.  A texture mapping is a pair of functions u(x,y) and v(x,y) which take
  25.  screen coordinates to texture coordinates.  This map gives you the texture
  26.  coordinates corresponding to any screen coordinate, and hence gives all
  27.  the information needed to render a textured plane.
  28.  
  29.  THE PROBLEM
  30.  ===========
  31.  
  32.  +-> y                    +-> u
  33.  |         SCREEN         |             TEXTURE
  34.  V x  *--                 V v  *------*
  35.       |  ---                   |      |
  36.       |     ---                |      |
  37.       |        --*             |      |
  38.       |          |             *------*
  39.       |          |
  40.       |        --*
  41.       |     ---
  42.       |  ---
  43.       *--                    Figure 1
  44.  
  45.  
  46.  
  47.  Plotting a DOOM-style wall using a square texture requires drawing a
  48.  parallelogram on the screen (Figure 1).  The very shape of this polygon
  49.  strongly suggests plotting a series of vertical strips of differing widths
  50.  in order to render it.  Since z is constant while y varies, there is no
  51.  effect due to perspective along these strips.  The strip plotter then
  52.  merely stretches a vertical strip from the texture into the vertical strip
  53.  on screen.  But how do we determine which strip?  In Wolfenstein 3D this
  54.  was easy, because the u coordinate can be explicitly calculated by the
  55.  raycasting engine.  However, this method is not available without
  56.  raycasting.  We require a method for calculating a series of u coordinates
  57.  which are perspectively correct.
  58.  
  59.  SIMPLEST APPROACH
  60.  =================
  61.  
  62.  A simplistic approach just interpolates u values linearly along the width
  63.  of the polygon.  E.g.
  64.  
  65.  uinc = 1/(right-left)
  66.  for (x = left, u = 0 ; x < right ; x++, u += uinc)
  67.  {
  68.    plot_strip(u);
  69.  }
  70.  
  71.  However, this does not take into account the effect of perspective fore-
  72.  shortening.
  73.  
  74.  To take perspective into account, it seems that for each x coordinate you
  75.  must
  76.  
  77.  1. Calculate the z coordinate of the point, and hence calculate the actual
  78.     x coordinate (by inverting the perspective transform)
  79.  2. Calculate the texture coordinate from this x value
  80.  
  81.  Step 2 is a lot of work and requires either a square root or a vector
  82.  rotation (if the angle of the line is precalculated).  Also, the
  83.  introduction of complex floating- or fixed-point calculations at this
  84.  stage of the rendering pipeline is undesirable.
  85.  
  86.  AN ALGORITHM
  87.  ============
  88.  
  89.  +-> y                    +-> u
  90.  |         SCREEN         |             TEXTURE
  91.  V x  *=-                 V v  *=-----*
  92.       | =---                   | =    |
  93.       |  == ---                |  ==  |
  94.       |    =   --*             |    = |
  95.       |     ==   |             *-----=*
  96.       |       =  |
  97.       |        ==*
  98.       |     ---
  99.       |  ---
  100.       *--                    Figure 2
  101.  
  102.  Figure 2 is the same as figure 1, but with the addition of a line which, in
  103.  texture space, is represented by the equation u = v.
  104.  Since the perspective transformation preserves straight lines (a fact
  105.  certain game authors might bear in mind ;-)  the line is straight in
  106.  screen space. Any point on the line in screen space therefore corresponds
  107.  to a pair of equal coordinates (u,u) in texture space.
  108.  
  109.  But we know that calculating values of v for a strip is easy (they are
  110.  linearly related) so if we can calculate the value of v for a point on
  111.  this line, then we automatically know the value of u.  Therefore, all we
  112.  need to do is trace this line in screen space (easy - it's a straight
  113.  line) and then for each column just find the v coordinate of the current
  114.  point on this line.  This gives us the u coordinate.
  115.  
  116.  SAMPLE CODE
  117.  ===========
  118.  
  119.  plot_wall(left,right,ytopleft,ybottomleft,ytopright,ybottomright)
  120.  {
  121.    /* assumes 128x128 textures */
  122.  
  123.    /* overall */
  124.    width = right - left
  125.    lheight = ybottomleft - ytopleft
  126.    rheight = ybottomright - ytopright
  127.  
  128.    /* top line */
  129.    y1 = ytopleft
  130.    y1inc = (ytopright - ytopleft)/width
  131.  
  132.    /* vertical */
  133.    height = lheight
  134.    heightinc = (rheight - lheight)/width
  135.  
  136.    /* magic line */
  137.    y2 = 0
  138.    y2inc = rheight/width
  139.  
  140.    for (x = left ; x < right ; x++)
  141.    {
  142.      u = (128 * y2)/height;
  143.      plot_strip(x, y1, height, u);
  144.  
  145.      y1 += y1inc
  146.      y2 += y2inc
  147.      height += heightinc
  148.    }
  149.  }
  150.  
  151.  EXTENSIONS
  152.  ==========
  153.  
  154.  This could easily be extended for non-square textures, but I feel that to
  155.  do so here would detract from the simplicity of the underlying algorithm.
  156.  
  157.  NOTES
  158.  =====
  159.  
  160.  I came up with this idea yesterday, when staring blankly at a doodle I'd
  161.  just found myself drawing!  Ping!  I seriously doubt that this really *is*
  162.  new, but it is certainly not widely known.  I haven't thought about
  163.  extending this to arbitrary polygons, but I think something groovy could
  164.  be done.
  165.  
  166.  By biggest problem is with the division to calculate u.  I don't know
  167.  enough about DDAs to comment, but it seems to me that there must be *some*
  168.  way of getting the value of u iteratively.  Any ideas?
  169.  
  170. --
  171. Eddie xxx (eddie@powerslv.demon.co.uk, ee@datcon.co.uk, leg@lize.it)
  172.