home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / qmapwos / src / tm_c.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-24  |  3.9 KB  |  165 lines

  1. /* QMAP: Quake level viewer
  2.  *
  3.  * tm_c.c  Copyright 1997 Sean Barrett
  4.  *
  5.  * Texture mapper in C
  6.  *
  7.  *   takes any size texture map, renders
  8.  *   it point-sampled with no lighting
  9.  *
  10.  */
  11.  
  12. #include "s.h"
  13. #include "fix.h"
  14. #include "tm.h"
  15.  
  16. char  *qmap_buf,    *qmap_tex;
  17. int    qmap_buf_row, qmap_tex_row;
  18. int    qmap_wid, qmap_ht;
  19.  
  20. int    qmap_row_table[768];      // max height of screen
  21. int    qmap_tex_row_table[258];  // max height of texture + 2
  22.  
  23. static double qmap_tmap[9];
  24.  
  25. // draw an affine (linear) span starting at dest, n pixels long,
  26. // starting at (u,v) in the texture and stepping by (du,dv) each pixel
  27.  
  28. int is_cached;
  29.  
  30. void qmap_draw_affine(int n, char *dest, fix u, fix v, fix du, fix dv)
  31. {
  32.    if (is_cached) {
  33.       while (n--) {
  34.          int iu = fix_int(u);
  35.          int iv = fix_int(v);
  36.          *dest++ = qmap_tex[qmap_tex_row_table[iv+1] + iu];
  37.          u += du;
  38.          v += dv;
  39.       }
  40.    } else {
  41.       while (n--) {
  42.          int iu = (fix_int(u)) & qmap_wid;
  43.          int iv = (fix_int(v)) & qmap_ht;
  44.          *dest++ = qmap_tex[qmap_tex_row_table[iv+1] + iu];
  45.          u += du;
  46.          v += dv;
  47.       }
  48.    }
  49. }
  50.  
  51. #define SUBDIV_SHIFT  4
  52. #define SUBDIV        (1 << SUBDIV_SHIFT)
  53.  
  54. // given a span (x0,y)..(x1,y), draw a perspective-correct span for it
  55. void qmap_draw_span(int y, int sx, int ex)
  56. {
  57.    double u0,v0,w0, u1,v1,w1, z;
  58.    int len, e, last = 0;
  59.    fix u,v,du,dv;
  60.  
  61.    // compute (u,v) at left end
  62.  
  63.    u0 = qmap_tmap[0] + sx * qmap_tmap[1] + y * qmap_tmap[2];
  64.    v0 = qmap_tmap[3] + sx * qmap_tmap[4] + y * qmap_tmap[5];
  65.    w0 = qmap_tmap[6] + sx * qmap_tmap[7] + y * qmap_tmap[8];
  66.  
  67.    z  =  1 / w0;
  68.    u0 = u0 * z;
  69.    v0 = v0 * z;
  70.  
  71. #ifdef CLAMP
  72.    // if you turn on clamping, you have to change qmap_wid & qmap_ht
  73.    // back to being wid&ht, not wid-1 & ht-1 as they are right now
  74.    if (u0 < 0) u0 = 0; else if (u0 >= qmap_wid) u0 = qmap_wid-0.01;
  75.    if (v0 < 0) v0 = 0; else if (v0 >= qmap_ht) v0 = qmap_ht-0.01;
  76. #endif
  77.  
  78.    for (;;) {
  79.       len = ex - sx;
  80.       if (len > SUBDIV)
  81.          len = SUBDIV;
  82.       else
  83.          last = 1;
  84.  
  85.       u = FLOAT_TO_FIX(u0);
  86.       v = FLOAT_TO_FIX(v0);
  87.  
  88.       if (len == 1) {
  89.          // shortcut out to avoid divide by 0 below
  90.          qmap_draw_affine(len, qmap_buf + qmap_row_table[y] + sx, u, v, 0, 0);
  91.          return;
  92.       }
  93.  
  94.       e = sx + len - last;
  95.  
  96.       u1 = qmap_tmap[0] + e * qmap_tmap[1] + y * qmap_tmap[2];
  97.       v1 = qmap_tmap[3] + e * qmap_tmap[4] + y * qmap_tmap[5];
  98.       w1 = qmap_tmap[6] + e * qmap_tmap[7] + y * qmap_tmap[8];
  99.  
  100.       z = 1 / w1;
  101.       u1 = u1 * z;
  102.       v1 = v1 * z;
  103.  
  104. #ifdef CLAMP
  105.       if (u1 < 0) u1 = 0; else if (u1 >= qmap_wid) u1 = qmap_wid-0.01;
  106.       if (v1 < 0) v1 = 0; else if (v1 >= qmap_ht) v1 = qmap_ht-0.01;
  107. #endif
  108.  
  109.       if (len == SUBDIV) {
  110.          du = (FLOAT_TO_FIX(u1) - u) >> SUBDIV_SHIFT;
  111.          dv = (FLOAT_TO_FIX(v1) - v) >> SUBDIV_SHIFT;
  112.       } else {
  113.          du = FLOAT_TO_FIX((u1-u0)/(len-last));
  114.          dv = FLOAT_TO_FIX((v1-v0)/(len-last));
  115.       }
  116.       if (du < 0) ++du;
  117.       if (dv < 0) ++dv;
  118.  
  119.       qmap_draw_affine(len, qmap_buf + qmap_row_table[y] + sx, u, v, du, dv);
  120.       if (last) 
  121.          break;
  122.  
  123.       sx += len;
  124.       u0 = u1;
  125.       v0 = v1;
  126.    }
  127. }
  128.  
  129. ///  setup global variables code
  130.  
  131. void qmap_set_output(char *where, int row)
  132. {
  133.    qmap_buf = where;
  134.    if (qmap_buf_row != row) {
  135.       int i;
  136.       qmap_buf_row = row;
  137.       for (i=0; i < 768; ++i)
  138.          qmap_row_table[i] = i * row;
  139.    }
  140. }
  141.  
  142. void qmap_set_texture(bitmap *bm)
  143. {
  144.    int row = bm->wid, ht = bm->ht;
  145.    qmap_tex = bm->bits;
  146.    qmap_wid = bm->wid-1;
  147.  
  148.    if (qmap_tex_row != row || qmap_ht != ht-1) {
  149.       int i;
  150.       qmap_tex_row = row;
  151.       qmap_ht = ht-1;
  152.       for (i=0; i < ht; ++i)
  153.          qmap_tex_row_table[i+1] = row * i;
  154.       qmap_tex_row_table[0] = qmap_tex_row_table[1];
  155.       qmap_tex_row_table[ht+1] = qmap_tex_row_table[ht];
  156.    }
  157. }
  158.  
  159. void qmap_set_texture_gradients(double *tmap_data)
  160. {
  161.    int i;
  162.    for (i=0; i < 9; ++i)
  163.       qmap_tmap[i] = tmap_data[i];
  164. }
  165.