home *** CD-ROM | disk | FTP | other *** search
- /* QMAP: Quake level viewer
- *
- * tmap3d.c Copyright 1997 Sean Barrett
- *
- * compute texture-mapping info that has to
- * look at stuff in 3d: mipmapping, texture gradient
- */
-
- #include <math.h>
- #include "3d.h"
- #include "bspfile.h"
- #include "tmap3d.h"
- #include "tm.h"
-
- #define DIST 256.0 // dist to switch first mip level
- #define DIST2 (DIST*DIST)
-
- int compute_mip_level(int face)
- {
- // dumb algorithm: grab 3d coordinate of some vertex,
- // compute dist from viewer
- int se = dfaces[face].firstedge;
- int e = dsurfedges[se];
- double dist;
- if (e < 0) e = -e;
- dist = dist2_from_viewer((vector *) &dvertexes[dedges[e].v[0]]) / DIST2;
- if (dist < 1) return 0;
- if (dist < 4) return 1;
- if (dist < 16) return 2;
- return 3;
- }
-
- // iterate over vertices of face, compute u&v coords, compute min & max
- void get_face_extent(int face, int *u0, int *v0, int *u1, int *v1)
- {
- float uv[32][2], u[4],v[4], umin,umax,vmin,vmax;
- int tex = dfaces[face].texinfo;
- int i,n = dfaces[face].numedges;
- int se = dfaces[face].firstedge;
- vector *loc;
-
- memcpy(u, texinfo[tex].vecs[0], sizeof(u));
- memcpy(v, texinfo[tex].vecs[1], sizeof(v));
-
- for (i=0; i < n; ++i) {
- int j = dsurfedges[se+i];
- if (j < 0)
- loc = (vector *) VERTEX(dedges[-j].v[1]);
- else
- loc = (vector *) VERTEX(dedges[ j].v[0]);
- uv[i][0] = loc->x*u[0] + loc->y*u[1] + loc->z*u[2] + u[3];
- uv[i][1] = loc->x*v[0] + loc->y*v[1] + loc->z*v[2] + v[3];
- }
- umin = umax = uv[0][0];
- vmin = vmax = uv[0][1];
- for (i=1; i < n; ++i) {
- if (uv[i][0] < umin) umin = uv[i][0];
- else if (uv[i][0] > umax) umax = uv[i][0];
- if (uv[i][1] < vmin) vmin = uv[i][1];
- else if (uv[i][1] > vmax) vmax = uv[i][1];
- }
- *u0 = FLOAT_TO_INT(umin) & ~15;
- *v0 = FLOAT_TO_INT(vmin) & ~15;
- *u1 = FLOAT_TO_INT(ceil(umax/16)) << 4;
- *v1 = FLOAT_TO_INT(ceil(vmax/16)) << 4;
- }
-
- void compute_texture_normal(vector *out, vector *u, vector *v)
- {
- out->x = u->y*v->z - u->z*v->y;
- out->y = u->z*v->x - u->x*v->z;
- out->z = u->x*v->y - u->y*v->x;
- }
-
- void setup_uv_vector(vector *out, vector *in, vector *norm, float *plane)
- {
- double dot = -(in->x*plane[0] + in->y*plane[1] + in->z*plane[2])
- / (norm->x*plane[0] + norm->y*plane[1] + norm->z*plane[2]);
- if (dot != 0) {
- vector temp = *in;
- temp.x += norm->x*dot;
- temp.y += norm->y*dot;
- temp.z += norm->z*dot;
- transform_vector(out, &temp);
- } else
- transform_vector(out, in);
- }
-
- // compute location of origin of texture (should precompute)
- void setup_origin_vector(vector *out, dplane_t *plane, vector *norm)
- {
- vector temp;
- float d = plane->dist / (norm->x*plane->normal[0]
- + norm->y*plane->normal[1] + norm->z*plane->normal[2]);
- temp.x = d * norm->x;
- temp.y = d * norm->y;
- temp.z = d * norm->z;
-
- transform_point_raw(out, &temp);
- }
-
- void compute_texture_gradients(int face, int tex, int mip, float u, float v)
- {
- double tmap_data[9];
- vector P,M,N;
- vector norm;
- dplane_t *plane = &dplanes[dfaces[face].planenum];
- float rescale = (8 >> mip) / 8.0;
-
- compute_texture_normal(&norm,
- (vector *) texinfo[tex].vecs[0], (vector *) texinfo[tex].vecs[1]);
- // project vectors onto face's plane, and transform
- setup_uv_vector(&M, (vector *) texinfo[tex].vecs[0], &norm, plane->normal);
- setup_uv_vector(&N, (vector *) texinfo[tex].vecs[1], &norm, plane->normal);
- setup_origin_vector(&P, plane, &norm);
-
- u -= texinfo[tex].vecs[0][3]; // adjust according to face's info
- v -= texinfo[tex].vecs[1][3]; // passed in values adjust for lightmap
-
- // we could just subtract (u,v) every time we compute a new (u,v);
- // instead we fold it into P:
- P.x += u * M.x + v * N.x;
- P.y += u * M.y + v * N.y;
- P.z += u * M.z + v * N.z;
-
- tmap_data[0] = P.x*N.y - P.y*N.x;
- tmap_data[1] = P.y*N.z - P.z*N.y;
- tmap_data[2] = P.x*N.z - P.z*N.x;
- tmap_data[3] = P.y*M.x - P.x*M.y;
- tmap_data[4] = P.z*M.y - P.y*M.z;
- tmap_data[5] = P.z*M.x - P.x*M.z;
- tmap_data[6] = N.x*M.y - N.y*M.x;
- tmap_data[7] = N.y*M.z - N.z*M.y;
- tmap_data[8] = N.x*M.z - N.z*M.x;
-
- // offset by center of screen--if this were folded into
- // transform translation we could avoid it
- tmap_data[0] -= tmap_data[1]*159.5 + tmap_data[2]*99.5;
- tmap_data[3] -= tmap_data[4]*159.5 + tmap_data[5]*99.5;
- tmap_data[6] -= tmap_data[7]*159.5 + tmap_data[8]*99.5;
-
- tmap_data[0] *= rescale;
- tmap_data[1] *= rescale;
- tmap_data[2] *= rescale;
- tmap_data[3] *= rescale;
- tmap_data[4] *= rescale;
- tmap_data[5] *= rescale;
-
- qmap_set_texture_gradients(tmap_data);
- }
-