home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / qmapwos / src / tmap3d.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-04  |  4.7 KB  |  151 lines

  1. /* QMAP: Quake level viewer
  2.  *
  3.  *   tmap3d.c   Copyright 1997 Sean Barrett
  4.  *
  5.  *  compute texture-mapping info that has to
  6.  *  look at stuff in 3d: mipmapping, texture gradient
  7.  */
  8.  
  9. #include <math.h>
  10. #include "3d.h"
  11. #include "bspfile.h"
  12. #include "tmap3d.h"
  13. #include "tm.h"
  14.  
  15. #define DIST  256.0    // dist to switch first mip level
  16. #define DIST2 (DIST*DIST)
  17.  
  18. int compute_mip_level(int face)
  19. {
  20.    // dumb algorithm: grab 3d coordinate of some vertex,
  21.    // compute dist from viewer
  22.    int se = dfaces[face].firstedge;
  23.    int e = dsurfedges[se];
  24.    double dist;
  25.    if (e < 0) e = -e;
  26.    dist = dist2_from_viewer((vector *) &dvertexes[dedges[e].v[0]]) / DIST2;
  27.    if (dist < 1) return 0;
  28.    if (dist < 4) return 1;
  29.    if (dist < 16) return 2;
  30.    return 3;
  31. }
  32.  
  33. // iterate over vertices of face, compute u&v coords, compute min & max
  34. void get_face_extent(int face, int *u0, int *v0, int *u1, int *v1)
  35. {
  36.    float uv[32][2], u[4],v[4], umin,umax,vmin,vmax;
  37.    int tex = dfaces[face].texinfo;
  38.    int i,n = dfaces[face].numedges;
  39.    int se = dfaces[face].firstedge;
  40.    vector *loc;
  41.  
  42.    memcpy(u, texinfo[tex].vecs[0], sizeof(u));
  43.    memcpy(v, texinfo[tex].vecs[1], sizeof(v));
  44.  
  45.    for (i=0; i < n; ++i) {
  46.       int j = dsurfedges[se+i];
  47.       if (j < 0)
  48.          loc = (vector *) VERTEX(dedges[-j].v[1]);
  49.       else
  50.          loc = (vector *) VERTEX(dedges[ j].v[0]);
  51.       uv[i][0] = loc->x*u[0] + loc->y*u[1] + loc->z*u[2] + u[3];
  52.       uv[i][1] = loc->x*v[0] + loc->y*v[1] + loc->z*v[2] + v[3];
  53.    }
  54.    umin = umax = uv[0][0];
  55.    vmin = vmax = uv[0][1];
  56.    for (i=1; i < n; ++i) {
  57.            if (uv[i][0] < umin) umin = uv[i][0];
  58.       else if (uv[i][0] > umax) umax = uv[i][0];
  59.            if (uv[i][1] < vmin) vmin = uv[i][1];
  60.       else if (uv[i][1] > vmax) vmax = uv[i][1];
  61.    }
  62.    *u0 = FLOAT_TO_INT(umin) & ~15;
  63.    *v0 = FLOAT_TO_INT(vmin) & ~15;
  64.    *u1 = FLOAT_TO_INT(ceil(umax/16)) << 4;
  65.    *v1 = FLOAT_TO_INT(ceil(vmax/16)) << 4;
  66. }
  67.  
  68. void compute_texture_normal(vector *out, vector *u, vector *v)
  69. {
  70.    out->x = u->y*v->z - u->z*v->y;
  71.    out->y = u->z*v->x - u->x*v->z;
  72.    out->z = u->x*v->y - u->y*v->x;
  73. }
  74.  
  75. void setup_uv_vector(vector *out, vector *in, vector *norm, float *plane)
  76. {
  77.    double dot = -(in->x*plane[0] + in->y*plane[1] + in->z*plane[2])
  78.               / (norm->x*plane[0] + norm->y*plane[1] + norm->z*plane[2]);
  79.    if (dot != 0) {
  80.       vector temp = *in;
  81.       temp.x += norm->x*dot;
  82.       temp.y += norm->y*dot;
  83.       temp.z += norm->z*dot;
  84.       transform_vector(out, &temp);
  85.    } else
  86.       transform_vector(out, in);
  87. }
  88.  
  89. // compute location of origin of texture (should precompute)
  90. void setup_origin_vector(vector *out, dplane_t *plane, vector *norm)
  91. {
  92.    vector temp;
  93.    float d =  plane->dist / (norm->x*plane->normal[0]
  94.                    + norm->y*plane->normal[1] + norm->z*plane->normal[2]);
  95.    temp.x = d * norm->x;
  96.    temp.y = d * norm->y;
  97.    temp.z = d * norm->z;
  98.  
  99.    transform_point_raw(out, &temp);
  100. }
  101.  
  102. void compute_texture_gradients(int face, int tex, int mip, float u, float v)
  103. {
  104.    double tmap_data[9];
  105.    vector P,M,N;
  106.    vector norm;
  107.    dplane_t *plane = &dplanes[dfaces[face].planenum];
  108.    float rescale = (8 >> mip) / 8.0;
  109.  
  110.    compute_texture_normal(&norm,
  111.          (vector *) texinfo[tex].vecs[0], (vector *) texinfo[tex].vecs[1]);
  112.       // project vectors onto face's plane, and transform
  113.    setup_uv_vector(&M, (vector *) texinfo[tex].vecs[0], &norm, plane->normal);
  114.    setup_uv_vector(&N, (vector *) texinfo[tex].vecs[1], &norm, plane->normal);
  115.    setup_origin_vector(&P, plane, &norm);
  116.  
  117.    u -= texinfo[tex].vecs[0][3];  // adjust according to face's info
  118.    v -= texinfo[tex].vecs[1][3];  // passed in values adjust for lightmap
  119.  
  120.    // we could just subtract (u,v) every time we compute a new (u,v);
  121.    // instead we fold it into P:
  122.    P.x += u * M.x + v * N.x;
  123.    P.y += u * M.y + v * N.y;
  124.    P.z += u * M.z + v * N.z;
  125.  
  126.    tmap_data[0] = P.x*N.y - P.y*N.x;
  127.    tmap_data[1] = P.y*N.z - P.z*N.y;
  128.    tmap_data[2] = P.x*N.z - P.z*N.x;
  129.    tmap_data[3] = P.y*M.x - P.x*M.y;
  130.    tmap_data[4] = P.z*M.y - P.y*M.z;
  131.    tmap_data[5] = P.z*M.x - P.x*M.z;
  132.    tmap_data[6] = N.x*M.y - N.y*M.x;
  133.    tmap_data[7] = N.y*M.z - N.z*M.y;
  134.    tmap_data[8] = N.x*M.z - N.z*M.x;
  135.  
  136.       // offset by center of screen--if this were folded into
  137.       // transform translation we could avoid it
  138.    tmap_data[0] -= tmap_data[1]*159.5 + tmap_data[2]*99.5;
  139.    tmap_data[3] -= tmap_data[4]*159.5 + tmap_data[5]*99.5;
  140.    tmap_data[6] -= tmap_data[7]*159.5 + tmap_data[8]*99.5;
  141.      
  142.    tmap_data[0] *= rescale;
  143.    tmap_data[1] *= rescale;
  144.    tmap_data[2] *= rescale;
  145.    tmap_data[3] *= rescale;
  146.    tmap_data[4] *= rescale;
  147.    tmap_data[5] *= rescale;
  148.  
  149.    qmap_set_texture_gradients(tmap_data);
  150. }
  151.