home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / qmapwos / src / clippoly.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-09  |  3.5 KB  |  133 lines

  1. /* QMAP: Quake level viewer
  2.  *
  3.  *    clippoly.c   Copyright 1997 Sean Barrett
  4.  *
  5.  *    clip polygon to view frustrum, in viewspace
  6.  */
  7.  
  8. #include "3d.h"
  9.  
  10. static point_3d pts[16], *clip_list1[40],*clip_list2[40];
  11.  
  12. #define X p.x
  13. #define Y p.y
  14. #define Z p.z
  15.  
  16. static void intersect(point_3d *out, point_3d *a, point_3d *b, float where)
  17. {
  18.    // intersection occurs 'where' % along the line from a to b
  19.  
  20.    out->X = a->X + (b->X - a->X) * where;
  21.    out->Y = a->Y + (b->Y - a->Y) * where;
  22.    out->Z = a->Z + (b->Z - a->Z) * where;
  23.  
  24.    transform_rotated_point(out);
  25. }
  26.  
  27. // compute 'where' for various clip planes
  28.  
  29. static double left_loc(point_3d *a, point_3d *b)
  30. {
  31.    return -(a->Z+a->X*clip_scale_x)/((b->X-a->X)*clip_scale_x + b->Z-a->Z);
  32. }
  33.  
  34. static double right_loc(point_3d *a, point_3d *b)
  35. {
  36.    return  (a->Z-a->X*clip_scale_x)/((b->X-a->X)*clip_scale_x - b->Z+a->Z);
  37. }
  38.  
  39. static double top_loc(point_3d *a, point_3d *b)
  40. {
  41.    return  (a->Z-a->Y*clip_scale_y)/((b->Y-a->Y)*clip_scale_y - b->Z+a->Z);
  42. }
  43.  
  44. static double bottom_loc(point_3d *a, point_3d *b)
  45. {
  46.    return -(a->Z+a->Y*clip_scale_y)/((b->Y-a->Y)*clip_scale_y + b->Z-a->Z);
  47. }
  48.  
  49. // clip the polygon to each of the view frustrum planes
  50. int clip_poly(int n, point_3d **vl, int codes_or, point_3d ***out_vl)
  51. {
  52.    int i,j,k,p=0; // p = index into temporary point pool
  53.    point_3d **cur;
  54.  
  55.    if (codes_or & CC_OFF_LEFT) {
  56.       cur = clip_list1;
  57.       k = 0;
  58.       j = n-1;
  59.       for (i=0; i < n; ++i) {
  60.          // process edge from j..i
  61.          // if j is inside, add it
  62.  
  63.          if (!(vl[j]->ccodes & CC_OFF_LEFT))
  64.             cur[k++] = vl[j];
  65.  
  66.          // if it crosses, add the intersection point
  67.  
  68.          if ((vl[j]->ccodes ^ vl[i]->ccodes) & CC_OFF_LEFT) {
  69.             intersect(&pts[p], vl[i], vl[j], left_loc(vl[i],vl[j]));
  70.             cur[k++] = &pts[p++];
  71.          }
  72.          j = i;
  73.       }
  74.       // move output list to be input
  75.       n = k;
  76.       vl = cur;
  77.    }
  78.    if (codes_or & CC_OFF_RIGHT) {
  79.       cur = (vl == clip_list1) ? clip_list2 : clip_list1;
  80.       k = 0;
  81.       j = n-1;
  82.       for (i=0; i < n; ++i) {
  83.          if (!(vl[j]->ccodes & CC_OFF_RIGHT))
  84.             cur[k++] = vl[j];
  85.          if ((vl[j]->ccodes ^ vl[i]->ccodes) & CC_OFF_RIGHT) {
  86.             intersect(&pts[p], vl[i], vl[j], right_loc(vl[i],vl[j]));
  87.             cur[k++] = &pts[p++];
  88.          }
  89.          j = i;
  90.       }
  91.       n = k;
  92.       vl = cur;
  93.    }
  94.    if (codes_or & CC_OFF_TOP) {
  95.       cur = (vl == clip_list1) ? clip_list2 : clip_list1;
  96.       k = 0;
  97.       j = n-1;
  98.       for (i=0; i < n; ++i) {
  99.          if (!(vl[j]->ccodes & CC_OFF_TOP))
  100.             cur[k++] = vl[j];
  101.          if ((vl[j]->ccodes ^ vl[i]->ccodes) & CC_OFF_TOP) {
  102.             intersect(&pts[p], vl[i], vl[j], top_loc(vl[i],vl[j]));
  103.             cur[k++] = &pts[p++];
  104.          }
  105.          j = i;
  106.       }
  107.       n = k;
  108.       vl = cur;
  109.    }
  110.    if (codes_or & CC_OFF_BOT) {
  111.       cur = (vl == clip_list1) ? clip_list2 : clip_list1;
  112.       k = 0;
  113.       j = n-1;
  114.       for (i=0; i < n; ++i) {
  115.          if (!(vl[j]->ccodes & CC_OFF_BOT))
  116.             cur[k++] = vl[j];
  117.          if ((vl[j]->ccodes ^ vl[i]->ccodes) & CC_OFF_BOT) {
  118.             intersect(&pts[p], vl[i], vl[j], bottom_loc(vl[i],vl[j]));
  119.             cur[k++] = &pts[p++];
  120.          }
  121.          j = i;
  122.       }
  123.       n = k;
  124.       vl = cur;
  125.    }
  126.    for (i=0; i < n; ++i)
  127.       if (vl[i]->ccodes & CC_BEHIND)
  128.          return 0;
  129.  
  130.    *out_vl = vl;
  131.    return n;
  132. }
  133.