round_cap.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:7k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*
  2.  * MODULE NAME: round_cap.c
  3.  *
  4.  * FUNCTION:
  5.  * This module contains code that draws the round end-cap for round
  6.  * join-style tubing.
  7.  *
  8.  * HISTORY:
  9.  * written by Linas Vepstas August/September 1991
  10.  * split into multiple compile units, Linas, October 1991
  11.  * added normal vectors Linas, October 1991
  12.  */
  13. #include <malloc.h>
  14. #include <stdlib.h>
  15. #include <math.h>
  16. #include <string.h> /* for the memcpy() subroutine */
  17. #include <GL/tube.h>
  18. #include "port.h"
  19. #include "gutil.h"
  20. #include "vvector.h"
  21. #include "extrude.h"
  22. #include "tube_gc.h"
  23. #include "intersect.h"
  24. #include "segment.h"
  25. /* ============================================================ */
  26. /* This routine does what it says: It draws the end-caps for the
  27.  * "round" join style.
  28.  */
  29. /* HACK ALERT HACK ALERT HACK ALERT HACK ALERT */
  30. /* This #define should be replaced by some adaptive thingy.
  31.  * the adaptiveness needs to depend on relative angles and diameter of
  32.  * extrusion relative to screen size (in pixels).
  33.  */
  34. #define __ROUND_TESS_PIECES 5
  35. void draw_round_style_cap_callback (int ncp,
  36.                                   double cap[][3],
  37.                                   float face_color[3],
  38.                                   gleDouble cut[3],
  39.                                   gleDouble bi[3],
  40.                                   double norms[][3],
  41.                                   int frontwards)
  42. {
  43.    double axis[3];
  44.    double xycut[3];
  45.    double theta;
  46.    double *last_contour, *next_contour;
  47.    double *last_norm, *next_norm;
  48.    double *cap_z;
  49.    double *tmp;
  50.    char *malloced_area;
  51.    int i, j, k;
  52.    double m[4][4];
  53.    if (face_color != NULL) C3F (face_color);
  54.    /* ------------ start setting up rotation matrix ------------- */
  55.    /* if the cut vector is NULL (this should only occur in
  56.     * a degenerate case), then we can't draw anything. return. */
  57.    if (cut == NULL) return;
  58.    /* make sure that the cut vector points inwards */
  59.    if (cut[2] > 0.0) {
  60.       VEC_SCALE (cut, -1.0, cut);
  61.    }
  62.    /* make sure that the bi vector points outwards */
  63.    if (bi[2] < 0.0) {
  64.       VEC_SCALE (bi, -1.0, bi);
  65.    }
  66.    /* determine the axis we are to rotate about to get bi-contour.
  67.     * Note that the axis will always lie in the x-y plane */
  68.    VEC_CROSS_PRODUCT (axis, cut, bi);
  69.    /* reverse the cut vector for the back cap -- 
  70.     * need to do this to get angle right */
  71.    if (!frontwards) {
  72.       VEC_SCALE (cut, -1.0, cut);
  73.    }
  74.    /* get angle to rotate by -- arccos of dot product of cut with cut
  75.     * projected into the x-y plane */
  76.    xycut [0] = 0.0;
  77.    xycut [1] = 0.0;
  78.    xycut [2] = 1.0;
  79.    VEC_PERP (xycut, cut, xycut);
  80.    VEC_NORMALIZE (xycut);
  81.    VEC_DOT_PRODUCT (theta, xycut, cut);
  82.    theta = acos (theta);
  83.    /* we'll tesselate round joins into a number of teeny pieces */
  84.    theta /= (double) __ROUND_TESS_PIECES;
  85.    /* get the matrix */
  86.    urot_axis_d (m, theta, axis);
  87.    /* ------------ done setting up rotation matrix ------------- */
  88.    /* This malloc is a fancy version of:
  89.     * last_contour = (double *) malloc (3*ncp*sizeof(double);
  90.     * next_contour = (double *) malloc (3*ncp*sizeof(double);
  91.     */
  92.    malloced_area = malloc ((4*3+1) *ncp*sizeof (double));
  93.    last_contour = (double *) malloced_area;
  94.    next_contour = last_contour +  3*ncp;
  95.    cap_z = next_contour + 3*ncp;
  96.    last_norm = cap_z + ncp;
  97.    next_norm = last_norm + 3*ncp;
  98.    /* make first copy of contour */
  99.    if (frontwards) {
  100.       for (j=0; j<ncp; j++) {
  101.          last_contour[3*j] = cap[j][0];
  102.          last_contour[3*j+1] = cap[j][1];
  103.          last_contour[3*j+2] = cap_z[j] = cap[j][2];
  104.       }
  105.       if (norms != NULL) {
  106.          for (j=0; j<ncp; j++) {
  107.             VEC_COPY ((&last_norm[3*j]), norms[j]);
  108.          }
  109.       }
  110.    } else {
  111.       /* in order for backfacing polygon removal to work correctly, have
  112.        * to have the sense in which the joins are drawn to be reversed 
  113.        * for the back cap.  This can be done by reversing the order of
  114.        * the contour points.  Normals are a bit trickier, since the 
  115.        * reversal is off-by-one for facet normals as compared to edge 
  116.        * normals. */
  117.       for (j=0; j<ncp; j++) {
  118.          k = ncp - j - 1;
  119.          last_contour[3*k] = cap[j][0];
  120.          last_contour[3*k+1] = cap[j][1];
  121.          last_contour[3*k+2] = cap_z[k] = cap[j][2];
  122.       }
  123.       if (norms != NULL) {
  124.          if (__TUBE_DRAW_FACET_NORMALS) {
  125.             for (j=0; j<ncp-1; j++) {
  126.                k = ncp - j - 2;
  127.                VEC_COPY ((&last_norm[3*k]), norms[j]);
  128.             }
  129.          } else {
  130.             for (j=0; j<ncp; j++) {
  131.                k = ncp - j - 1;
  132.                VEC_COPY ((&last_norm[3*k]), norms[j]);
  133.             }
  134.          }
  135.       }
  136.    }
  137.    /* &&&&&&&&&&&&&& start drawing cap &&&&&&&&&&&&& */
  138.    for (i=0; i<__ROUND_TESS_PIECES; i++) {
  139.       for (j=0; j<ncp; j++) {
  140.          next_contour [3*j+2] -= cap_z[j];
  141.          last_contour [3*j+2] -= cap_z[j];
  142.          MAT_DOT_VEC_3X3 ( (&next_contour[3*j]), m, (&last_contour[3*j]));
  143.          next_contour [3*j+2] += cap_z[j];
  144.          last_contour [3*j+2] += cap_z[j];
  145.       }
  146.       if (norms != NULL) {
  147.          for (j=0; j<ncp; j++) {
  148.             MAT_DOT_VEC_3X3 ( (&next_norm[3*j]), m, (&last_norm[3*j]));
  149.          }
  150.       }
  151.       /* OK, now render it all */
  152.       if (norms == NULL) {
  153.          draw_segment_plain (ncp, (gleVector *) next_contour, 
  154.                                   (gleVector *) last_contour, 0, 0.0);
  155.       } else
  156.       if (__TUBE_DRAW_FACET_NORMALS) {
  157.          draw_binorm_segment_facet_n (ncp, 
  158.                                (gleVector *) next_contour, 
  159.                                (gleVector *) last_contour,
  160.                                (gleVector *) next_norm, 
  161.                                (gleVector *) last_norm, 0, 0.0);
  162.       } else {
  163.          draw_binorm_segment_edge_n (ncp,
  164.                                (gleVector *) next_contour, 
  165.                                (gleVector *) last_contour,
  166.                                (gleVector *) next_norm, 
  167.                                (gleVector *) last_norm, 0, 0.0);
  168.      }
  169.       /* swap contours */
  170.       tmp = next_contour;
  171.       next_contour = last_contour;
  172.       last_contour = tmp;
  173.       tmp = next_norm;
  174.       next_norm = last_norm;
  175.       last_norm = tmp;
  176.    }
  177.    /* &&&&&&&&&&&&&& end drawing cap &&&&&&&&&&&&& */
  178.    /* Thou shalt not leak memory */
  179.    free (malloced_area);
  180. }
  181. /* ==================== END OF FILE =========================== */