home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / qmapwos / src / 3d.c next >
Encoding:
C/C++ Source or Header  |  1997-06-09  |  5.6 KB  |  217 lines

  1. /* QMAP: Quake level viewer
  2.  *
  3.  *   3d.c  Copyright 1997 Sean Barrett
  4.  *
  5.  *   general 3d math
  6.  */
  7.  
  8. #include <math.h>
  9. #include <string.h>
  10. #include "3d.h"
  11. #include "bspfile.h"
  12.  
  13. double dot_vec_dbl(double *a, vector *b)
  14. {
  15.    return a[0]*b->x + a[1]*b->y + a[2]*b->z;
  16. }
  17.  
  18. void rot_x(double *v, fixang ang)
  19. {
  20.    double s = sin(ang * 3.141592 / 0x8000);
  21.    double c = cos(ang * 3.141592 / 0x8000);
  22.    double y,z;
  23.  
  24.    y =  c * v[1] + s * v[2];
  25.    z = -s * v[1] + c * v[2];
  26.    v[1] = y;
  27.    v[2] = z;
  28. }
  29.  
  30. void rot_y(double *v, fixang ang)
  31. {
  32.    double s = sin(ang * 3.141592 / 0x8000);
  33.    double c = cos(ang * 3.141592 / 0x8000);
  34.    double x,z;
  35.  
  36.    z =  c * v[2] + s * v[0];
  37.    x = -s * v[2] + c * v[0];
  38.    v[0] = x;
  39.    v[2] = z;
  40. }
  41.  
  42. void rot_z(double *v, fixang ang)
  43. {
  44.    double s = sin(ang * 3.141592 / 0x8000);
  45.    double c = cos(ang * 3.141592 / 0x8000);
  46.    double x,y;
  47.  
  48.    x =  c * v[0] + s * v[1];
  49.    y = -s * v[0] + c * v[1];
  50.    v[0] = x;
  51.    v[1] = y;
  52. }
  53.  
  54. void rotate(double *x, angvec *ang)
  55. {
  56.    rot_y(x, ang->ty);  // bank
  57.    rot_x(x, ang->tx);  // pitch
  58.    rot_z(x, ang->tz);  // yaw
  59. }
  60.  
  61. static double main_matrix[3][3], view_matrix[3][3], translate[3];
  62. static vector cam_loc;
  63.  
  64. static fix clip_x_low, clip_x_high, clip_y_low, clip_y_high;
  65.  
  66. static float proj_scale_x = 160, proj_scale_y = 160 * 200 / 240;
  67. static float xcenter = 159.5, ycenter = 99.5;
  68. static float near_clip = 0.01, near_code = 16.0;
  69.  
  70. double clip_scale_x, clip_scale_y;
  71.  
  72. void set_view_info(vector *loc, angvec *ang)
  73. {
  74.    int i;
  75.    cam_loc = *loc;
  76.  
  77.    clip_x_low = -0x8000;
  78.    clip_x_high = fix_make(320,0)-0x8000;
  79.    clip_y_low = -0x8000;
  80.    clip_y_high = fix_make(200,0)-0x8000;
  81.  
  82.    clip_scale_x = 1 / 160.0;
  83.    clip_scale_y = 1 / 100.0;
  84.  
  85.    // compute rotation matrix
  86.    memset(view_matrix, 0, sizeof(view_matrix));
  87.    view_matrix[0][0] = view_matrix[1][1] = view_matrix[2][2] = 1;
  88.    rotate(view_matrix[0], ang);
  89.    rotate(view_matrix[1], ang);
  90.    rotate(view_matrix[2], ang);
  91.    memcpy(main_matrix, view_matrix, sizeof(view_matrix));
  92.  
  93.    // so (1,0,0) in camera space maps to view_matrix[0] in world space.
  94.    // thus we multiply on the right by a worldspace vector to transform
  95.    // it to camera space.
  96.    // now, to account for translation, we just subtract the camera
  97.    // center before multiplying
  98.    translate[0] = loc->x;
  99.    translate[1] = loc->y;
  100.    translate[2] = loc->z;
  101.  
  102.    // roll projection math into transformation
  103.    for (i=0; i < 3; ++i) {
  104.       view_matrix[0][i] *= proj_scale_x;
  105.       view_matrix[2][i] *= proj_scale_y;
  106.    }
  107. }
  108.  
  109. double dist2_from_viewer(vector *in)
  110. {
  111.    vector temp;
  112.    temp.x = in->x - cam_loc.x;
  113.    temp.y = in->y - cam_loc.y;
  114.    temp.z = in->z - cam_loc.z;
  115.  
  116.    return temp.x*temp.x + temp.y*temp.y + temp.z*temp.z;
  117. }
  118.  
  119. void rotate_c2w(vector *dest, vector *src)
  120. {
  121.    dest->x = src->x * main_matrix[0][0]
  122.            + src->y * main_matrix[1][0]
  123.            + src->z * main_matrix[2][0];
  124.    dest->y = src->x * main_matrix[0][1]
  125.            + src->y * main_matrix[1][1]
  126.            + src->z * main_matrix[2][1];
  127.    dest->z = src->x * main_matrix[0][2]
  128.            + src->y * main_matrix[1][2]
  129.            + src->z * main_matrix[2][2];
  130. }
  131.  
  132. void rotate_vec(vector *item)
  133. {
  134.    vector temp;
  135.    temp = *item;
  136.    rotate_c2w(item, &temp);
  137. }
  138.  
  139. void compute_plane(dplane_t *plane, float x, float y, float z)
  140. {
  141.    vector temp, temp2;
  142.    temp2.x = x; temp2.y = z; temp2.z = y;
  143.    rotate_c2w(&temp, &temp2);
  144.    plane->normal[0] = temp.x;
  145.    plane->normal[1] = temp.y;
  146.    plane->normal[2] = temp.z;
  147.    plane->dist = temp.x*cam_loc.x + temp.y*cam_loc.y + temp.z*cam_loc.z;
  148. }
  149.  
  150. void compute_view_frustrum(dplane_t *planes)
  151. {
  152.    compute_plane(planes+0, -1,  0, 1);
  153.    compute_plane(planes+1,  1,  0, 1);
  154.    compute_plane(planes+2,  0,  1, 1);
  155.    compute_plane(planes+3,  0, -1, 1);
  156. }
  157.  
  158. void transform_point_raw(vector *out, vector *in)
  159. {
  160.    vector temp;
  161.    temp.x = in->x - translate[0];
  162.    temp.y = in->y - translate[1];
  163.    temp.z = in->z - translate[2];
  164.  
  165.    out->x = dot_vec_dbl(view_matrix[0], &temp);
  166.    out->z = dot_vec_dbl(view_matrix[1], &temp);
  167.    out->y = dot_vec_dbl(view_matrix[2], &temp);
  168. }
  169.  
  170. void transform_vector(vector *out, vector *in)
  171. {
  172.    vector temp = *in;
  173.    out->x = dot_vec_dbl(view_matrix[0], &temp);
  174.    out->z = dot_vec_dbl(view_matrix[1], &temp);
  175.    out->y = dot_vec_dbl(view_matrix[2], &temp);
  176. }
  177.  
  178. void project_point(point_3d *p)
  179. {
  180.    if (p->p.z >= near_clip) {
  181.       double div = 1.0 / p->p.z;
  182.       p->sx = FLOAT_TO_FIX( p->p.x * div + xcenter);
  183.       p->sy = FLOAT_TO_FIX(-p->p.y * div + ycenter);
  184.    }
  185. }
  186.  
  187. void code_point(point_3d *p)
  188. {
  189.    if (p->p.z >= near_code) {
  190.       // if point is far enough away, code in 2d from fixedpoint (faster)
  191.            if (p->sx < clip_x_low)  p->ccodes = CC_OFF_LEFT;
  192.       else if (p->sx > clip_x_high) p->ccodes = CC_OFF_RIGHT;
  193.       else                          p->ccodes = 0;
  194.            if (p->sy < clip_y_low)  p->ccodes |= CC_OFF_TOP;
  195.       else if (p->sy > clip_y_high) p->ccodes |= CC_OFF_BOT;
  196.    } else {
  197.       p->ccodes = (p->p.z > 0) ? 0 : CC_BEHIND;
  198.       if (p->p.x * clip_scale_x < -p->p.z) p->ccodes |= CC_OFF_LEFT;
  199.       if (p->p.x * clip_scale_x >  p->p.z) p->ccodes |= CC_OFF_RIGHT;
  200.       if (p->p.y * clip_scale_y >  p->p.z) p->ccodes |= CC_OFF_TOP;
  201.       if (p->p.y * clip_scale_y < -p->p.z) p->ccodes |= CC_OFF_BOT;
  202.    }
  203. }
  204.  
  205. void transform_point(point_3d *p, vector *v)
  206. {
  207.    transform_point_raw(&p->p, v);
  208.    project_point(p);
  209.    code_point(p);
  210. }
  211.  
  212. void transform_rotated_point(point_3d *p)
  213. {
  214.    project_point(p);
  215.    code_point(p);
  216. }
  217.