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

GIS编程

开发平台:

Visual C++

  1. /*
  2.  * MODULE NAME: ex_angle.c
  3.  *
  4.  * FUNCTION: 
  5.  * This module contains code that draws extrusions with angled
  6.  * joins ("angle join style").  It also inserts colors and normals 
  7.  * where necessary, if appropriate.
  8.  *
  9.  * HISTORY:
  10.  * written by Linas Vepstas August/September 1991
  11.  * split into multiple compile units, Linas, October 1991
  12.  * added normal vectors Linas, October 1991
  13.  * "code complete" (that is, I'm done), Linas Vepstas, October 1991
  14.  * work around OpenGL's lack of support for concave polys, June 1994
  15.  */
  16. #include <stdlib.h>
  17. #include <math.h>
  18. #include <string.h> /* for the memcpy() subroutine */
  19. #include <GL/tube.h>
  20. #include "port.h"
  21. #include "gutil.h"
  22. #include "vvector.h"
  23. #include "tube_gc.h"
  24. #include "extrude.h"
  25. #include "intersect.h"
  26. #include "segment.h"
  27. /* ============================================================ */
  28. /*
  29.  * Algorithmic trivia:
  30.  * 
  31.  * There is a slight bit of trivia which the super-duper exacto coder
  32.  * needs to know about the code in this module. It is this:
  33.  *
  34.  * This module attempts to correctly treat contour normal vectors 
  35.  * by applying the inverse transpose of the 2D contour affine
  36.  * transformation to the 2D contour normals.  This is perfectly correct,
  37.  * when applied to the "raw" join style.  However, if the affine transform
  38.  * has a strong rotational component, AND the join style is angle or
  39.  * cut, then the normal vectors would continue to rotate as the
  40.  * intersect point is extrapolated. 
  41.  * 
  42.  * The extrapolation of the inverse-transpose matrix to the intersection
  43.  * point is not done.  This would appear to be overkill for most
  44.  * situations.  The viewer might possibly detect an artifact of the 
  45.  * failure to do this correction IF all three of the following criteria 
  46.  * were met:
  47.  * 1) The affine xform has a strong rotational component,
  48.  * 2) The angle between two succesive segments is sharp (greater than 15 or
  49.  *    30 degrees).
  50.  * 3) The join style is angle or cut.
  51.  *
  52.  * However, I beleive that it is highly unlikely that the viewer will
  53.  * detect any artifacts. The reason I beleive this is that a strong
  54.  * rotational component will twist a segment so strongly that the more
  55.  * visible artifact will be that a segment is composed of triangle strips.
  56.  * As the user attempts to minimize the tesselation artifacts by shortening
  57.  * segments, then the rotational component will decrease in proportion,
  58.  * and the lighting artifact will fall away.
  59.  *
  60.  * To summarize, there is a slight inexactness in this code.  The author
  61.  * of the code beleives that this inexactness results in miniscule
  62.  * errors in every situation.
  63.  *
  64.  * Linas Vepstas March 1993
  65.  */
  66. /* ============================================================ */
  67. void draw_angle_style_front_cap (int ncp, /* number of contour points */
  68.                            gleDouble bi[3], /* biscetor */
  69.                            gleDouble point_array[][3]) /* polyline */
  70. {
  71.    int j;
  72. #ifdef OPENGL_10
  73.    GLUtriangulatorObj *tobj;
  74. #endif /* OPENGL_10 */
  75.    if (bi[2] < 0.0) {
  76.       VEC_SCALE (bi, -1.0, bi); 
  77.    }
  78. #ifdef GL_32
  79.    /* old-style gl handles concave polygons no problem, so the code is
  80.     * simple.  New-style gl is a lot more tricky. */
  81.    /* draw the end cap */
  82.    BGNPOLYGON ();
  83.    N3F (bi);
  84.    for (j=0; j<ncp; j++) {
  85.       V3F (point_array[j], j, FRONT_CAP);
  86.    }
  87.    ENDPOLYGON ();
  88. #endif /* GL_32 */
  89. #ifdef OPENGL_10
  90.    N3F(bi);
  91.    tobj = gluNewTess ();
  92.    gluTessCallback (tobj, GLU_BEGIN, glBegin);
  93.    gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
  94.    gluTessCallback (tobj, GLU_END, glEnd);
  95.    gluBeginPolygon (tobj);
  96.    for (j=0; j<ncp; j++) {
  97.       gluTessVertex (tobj, point_array[j], point_array[j]);
  98.    }
  99.    gluEndPolygon (tobj);
  100.    gluDeleteTess (tobj);
  101. #endif /* OPENGL_10 */
  102. }
  103. /* ============================================================ */
  104. void draw_angle_style_back_cap (int ncp, /* number of contour points */
  105.                            gleDouble bi[3], /* biscetor */
  106.                            gleDouble point_array[][3]) /* polyline */
  107. {
  108.    int j;
  109. #ifdef OPENGL_10
  110.    GLUtriangulatorObj *tobj;
  111. #endif /* OPENGL_10 */
  112.    if (bi[2] > 0.0) {
  113.       VEC_SCALE (bi, -1.0, bi); 
  114.    }
  115. #ifdef GL_32
  116.    /* old-style gl handles concave polygons no problem, so the code is
  117.     * simple.  New-style gl is a lot more tricky. */
  118.    /* draw the end cap */
  119.    BGNPOLYGON ();
  120.    N3F (bi);
  121.    for (j=ncp-1; j>=0; j--) {
  122.       V3F (point_array[j], j, BACK_CAP);
  123.    }
  124.    ENDPOLYGON ();
  125. #endif /* GL_32 */
  126. #ifdef OPENGL_10
  127.    N3F (bi);
  128.    tobj = gluNewTess ();
  129.    gluTessCallback (tobj, GLU_BEGIN, glBegin);
  130.    gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
  131.    gluTessCallback (tobj, GLU_END, glEnd);
  132.    gluBeginPolygon (tobj);
  133.    for (j=ncp-1; j>=0; j--) {
  134.       gluTessVertex (tobj, point_array[j], point_array[j]);
  135.    }
  136.    gluEndPolygon (tobj);
  137.    gluDeleteTess (tobj);
  138. #endif /* OPENGL_10 */
  139. }
  140. /* ============================================================ */
  141. void extrusion_angle_join (int ncp, /* number of contour points */
  142.                            gleDouble contour[][2], /* 2D contour */
  143.                            gleDouble cont_normal[][2], /* 2D normal vecs */
  144.                            gleDouble up[3], /* up vector for contour */
  145.                            int npoints, /* numpoints in poly-line */
  146.                            gleDouble point_array[][3], /* polyline */
  147.                            float color_array[][3], /* color of polyline */
  148.                            gleDouble xform_array[][2][3])  /* 2D contour xforms */
  149. {
  150.    int i, j;
  151.    int inext, inextnext;
  152.    gleDouble m[4][4];
  153.    gleDouble len;
  154.    gleDouble len_seg;
  155.    gleDouble diff[3];
  156.    gleDouble bi_0[3], bi_1[3]; /* bisecting plane */
  157.    gleDouble bisector_0[3], bisector_1[3]; /* bisecting plane */
  158.    gleDouble end_point_0[3], end_point_1[3]; 
  159.    gleDouble origin[3], neg_z[3];
  160.    gleDouble yup[3]; /* alternate up vector */
  161.    gleDouble *front_loop, *back_loop;   /* contours in 3D */
  162.    char * mem_anchor;
  163.    double *norm_loop; 
  164.    double *front_norm, *back_norm, *tmp; /* contour normals in 3D */
  165.    int first_time;
  166.    /* By definition, the contour passed in has its up vector pointing in
  167.     * the y direction */
  168.    if (up == NULL) {
  169.       yup[0] = 0.0;
  170.       yup[1] = 1.0;
  171.       yup[2] = 0.0;
  172.    } else {
  173.       VEC_COPY(yup, up);
  174.    }
  175.    /* ========== "up" vector sanity check ========== */
  176.    (void) up_sanity_check (yup, npoints, point_array);
  177.    /* the origin is at the origin */
  178.    origin [0] = 0.0;
  179.    origin [1] = 0.0;
  180.    origin [2] = 0.0;
  181.    /* and neg_z is at neg z */
  182.    neg_z[0] = 0.0;
  183.    neg_z[1] = 0.0;
  184.    neg_z[2] = 1.0;
  185.    /* ignore all segments of zero length */
  186.    i = 1;
  187.    inext = i;
  188.    FIND_NON_DEGENERATE_POINT (inext, npoints, len, diff, point_array);
  189.    len_seg = len; /* store for later use */
  190.    /* get the bisecting plane */
  191.    bisecting_plane (bi_0, point_array[0], 
  192.                           point_array[1], 
  193.                           point_array[inext]);
  194.    /* reflect the up vector in the bisecting plane */
  195.    VEC_REFLECT (yup, yup, bi_0);
  196.    /* malloc the storage we'll need for relaying changed contours to the
  197.     * drawing routines. */
  198.    mem_anchor =  malloc (2 * 3 * ncp * sizeof(double)
  199.                       +  2 * 3 * ncp * sizeof(gleDouble));
  200.    front_loop = (gleDouble *) mem_anchor;
  201.    back_loop = front_loop + 3 * ncp;
  202.    front_norm = (double *) (back_loop + 3 * ncp);
  203.    back_norm = front_norm + 3 * ncp;
  204.    norm_loop = front_norm;
  205.    /* may as well get the normals set up now */
  206.    if (cont_normal != NULL) {
  207.       if (xform_array == NULL) {
  208.          for (j=0; j<ncp; j++) {
  209.             norm_loop[3*j] = cont_normal[j][0];
  210.             norm_loop[3*j+1] = cont_normal[j][1];
  211.             norm_loop[3*j+2] = 0.0;
  212.          }
  213.       } else {
  214.          for (j=0; j<ncp; j++) {
  215.             NORM_XFORM_2X2 ( (&front_norm[3*j]),
  216.                               xform_array[inext-1],
  217.                               cont_normal [j]);
  218.             front_norm[3*j+2] = 0.0;
  219.             back_norm[3*j+2] = 0.0;
  220.          }
  221.       }
  222.    }
  223.    first_time = TRUE;
  224.    /* draw tubing, not doing the first segment */
  225.    while (inext<npoints-1) {
  226.       inextnext = inext;
  227.       /* ignore all segments of zero length */
  228.       FIND_NON_DEGENERATE_POINT (inextnext, npoints, len, diff, point_array);
  229.       /* get the next bisecting plane */
  230.       bisecting_plane (bi_1, point_array[i], 
  231.                              point_array[inext], 
  232.                              point_array[inextnext]);  
  233.       /* rotate so that z-axis points down v2-v1 axis, 
  234.        * and so that origen is at v1 */
  235.       uviewpoint (m, point_array[i], point_array[inext], yup);
  236.       PUSHMATRIX ();
  237.       MULTMATRIX (m);
  238.       /* rotate the bisecting planes into the local coordinate system */
  239.       MAT_DOT_VEC_3X3 (bisector_0, m, bi_0);
  240.       MAT_DOT_VEC_3X3 (bisector_1, m, bi_1);
  241.       neg_z[2] = -len_seg;
  242.       /* draw the tube */
  243.       /* --------- START OF TMESH GENERATION -------------- */
  244.       for (j=0; j<ncp; j++) {
  245.          /* if there are normals, and there are either affine xforms, OR
  246.           * path-edge normals need to be drawn, then compute local
  247.           * coordinate system normals. 
  248.           */
  249.          if (cont_normal != NULL) {
  250.           
  251.             /* set up the back normals. (The front normals we inherit
  252.              * from previous pass through the loop) */
  253.             if (xform_array != NULL) {
  254.                /* do up the normal vectors with the inverse transpose */
  255.                NORM_XFORM_2X2 ( (&back_norm[3*j]),
  256.                                  xform_array[inext],
  257.                                  cont_normal [j]);
  258.             }
  259.             /* Note that if the xform array is NULL, then normals are
  260.              * constant, and are set up outside of the loop.
  261.              */
  262.             /* 
  263.              * if there are normal vectors, and the style calls for it, 
  264.              * then we want to project the normal vectors into the
  265.              * bisecting plane. (This style is needed to make toroids, etc. 
  266.              * look good: Without this, segmentation artifacts show up
  267.              * under lighting.
  268.              */
  269.             if (__TUBE_DRAW_PATH_EDGE_NORMALS) {
  270.                /* Hmm, if no affine xforms, then we haven't yet set
  271.                 * back vector. So do it. */
  272.                if (xform_array == NULL) {
  273.                   back_norm[3*j] = cont_normal[j][0];
  274.                   back_norm[3*j+1] = cont_normal[j][1];
  275.                }
  276.    
  277.                /* now, start with a fresh normal (z component equal to
  278.                 * zero), project onto bisecting plane (by computing 
  279.                 * perpendicular componenet to bisect vector, and renormalize 
  280.                 * (since projected vector is not of unit length */ 
  281.                front_norm[3*j+2] = 0.0;
  282.                VEC_PERP ((&front_norm[3*j]), (&front_norm[3*j]), bisector_0);
  283.                VEC_NORMALIZE ((&front_norm[3*j]));
  284.     
  285.                back_norm[3*j+2] = 0.0;
  286.                VEC_PERP ((&back_norm[3*j]), (&back_norm[3*j]), bisector_1);
  287.                VEC_NORMALIZE ((&back_norm[3*j]));
  288.             } 
  289.          } 
  290.          /* Next, we want to define segements. We find the endpoints of
  291.           * the segments by intersecting the contour with the bisecting
  292.           * plane.  If there is no local affine transform, this is easy.
  293.           *
  294.           * If there is an affine tranform, then we want to remove the
  295.           * torsional component, so that the intersection points won't
  296.           * get twisted out of shape.  We do this by applying the
  297.           * local affine transform to the entire coordinate system.
  298.           */
  299.          if (xform_array == NULL) {
  300.             end_point_0 [0] = contour[j][0];
  301.             end_point_0 [1] = contour[j][1];
  302.    
  303.             end_point_1 [0] = contour[j][0];
  304.             end_point_1 [1] = contour[j][1];
  305.          } else {
  306.             /* transform the contour points with the local xform */
  307.             MAT_DOT_VEC_2X3 (end_point_0,
  308.                              xform_array[inext-1], contour[j]);
  309.             MAT_DOT_VEC_2X3 (end_point_1,
  310.                              xform_array[inext-1], contour[j]);
  311.          }
  312.          end_point_0 [2] = 0.0;
  313.          end_point_1 [2] = - len_seg;
  314.          /* The two end-points define a line.  Intersect this line
  315.           * against the clipping plane defined by the PREVIOUS
  316.           * tube segment.  */
  317.          INNERSECT ((&front_loop[3*j]), /* intersection point (returned) */
  318.                     origin, /* point on intersecting plane */
  319.                     bisector_0, /* normal vector to plane */
  320.                     end_point_0, /* point on line */
  321.                     end_point_1); /* another point on the line */
  322.          /* The two end-points define a line.  Intersect this line
  323.           * against the clipping plane defined by the NEXT
  324.           * tube segment.  */
  325.          /* if there's an affine coordinate change, be sure to use it */
  326.          if (xform_array != NULL) {
  327.             /* transform the contour points with the local xform */
  328.             MAT_DOT_VEC_2X3 (end_point_0,
  329.                              xform_array[inext], contour[j]);
  330.             MAT_DOT_VEC_2X3 (end_point_1,
  331.                              xform_array[inext], contour[j]);
  332.          }
  333.          INNERSECT ((&back_loop[3*j]), /* intersection point (returned) */
  334.                     neg_z, /* point on intersecting plane */
  335.                     bisector_1, /* normal vector to plane */
  336.                     end_point_0, /* point on line */
  337.                     end_point_1); /* another point on the line */
  338.       }
  339.       /* --------- END OF TMESH GENERATION -------------- */
  340.       /* v^v^v^v^v^v^v^v^v  BEGIN END CAPS v^v^v^v^v^v^v^v^v^v^v^v */
  341.       /* if end caps are required, draw them. But don't draw any 
  342.        * but the very first and last caps */
  343.       if (__TUBE_DRAW_CAP) {
  344.          if (first_time) {
  345.             if (color_array != NULL) C3F (color_array[inext-1]);
  346.             first_time = FALSE;
  347.             draw_angle_style_front_cap (ncp, bisector_0, (gleVector *) front_loop);
  348.          }
  349.          if (inext == npoints-2) {
  350.             if (color_array != NULL) C3F (color_array[inext]);
  351.             draw_angle_style_back_cap (ncp, bisector_1, (gleVector *) back_loop);
  352.          }
  353.       }
  354.       /* v^v^v^v^v^v^v^v^v  END END CAPS v^v^v^v^v^v^v^v^v^v^v^v */
  355.       /* |||||||||||||||||| START SEGMENT DRAW |||||||||||||||||||| */
  356.       /* There are six different cases we can have for presence and/or
  357.        * absecnce of colors and normals, and for interpretation of
  358.        * normals. The blechy set of nested if statements below
  359.        * branch to each of the six cases */
  360.       if ((xform_array == NULL) && (!__TUBE_DRAW_PATH_EDGE_NORMALS)) {
  361.          if (color_array == NULL) {
  362.             if (cont_normal == NULL) {
  363.                draw_segment_plain (ncp, (gleVector *) front_loop,
  364.                                         (gleVector *) back_loop, inext, len_seg);
  365.             } else
  366.             if (__TUBE_DRAW_FACET_NORMALS) {
  367.                draw_segment_facet_n (ncp, (gleVector *) front_loop,
  368.                                           (gleVector *) back_loop, 
  369.                                           (gleVector *) norm_loop, inext, len_seg);
  370.             } else {
  371.                draw_segment_edge_n (ncp, (gleVector *) front_loop, 
  372.                                          (gleVector *) back_loop, 
  373.                                          (gleVector *) norm_loop, inext, len_seg);
  374.             }
  375.          } else {
  376.             if (cont_normal == NULL) {
  377.                draw_segment_color (ncp, (gleVector *) front_loop, 
  378.                                         (gleVector *) back_loop, 
  379.                                    color_array[inext-1],
  380.                                    color_array[inext], inext, len_seg);
  381.             } else
  382.             if (__TUBE_DRAW_FACET_NORMALS) {
  383.                draw_segment_c_and_facet_n (ncp, 
  384.                                    (gleVector *) front_loop, 
  385.                                    (gleVector *) back_loop, 
  386.                                    (gleVector *) norm_loop,
  387.                                    color_array[inext-1],
  388.                                    color_array[inext], inext, len_seg);
  389.             } else {
  390.                draw_segment_c_and_edge_n (ncp, 
  391.                                    (gleVector *) front_loop, 
  392.                                    (gleVector *) back_loop, 
  393.                                    (gleVector *) norm_loop,
  394.                                    color_array[inext-1],
  395.                                    color_array[inext], inext, len_seg);
  396.              }
  397.           }
  398.       } else {
  399.          if (color_array == NULL) {
  400.             if (cont_normal == NULL) {
  401.                draw_segment_plain (ncp, (gleVector *) front_loop, 
  402.                                         (gleVector *)  back_loop, inext, len_seg);
  403.             } else 
  404.             if (__TUBE_DRAW_FACET_NORMALS) {
  405.                draw_binorm_segment_facet_n (ncp, (gleVector *) front_loop, 
  406.                                                  (gleVector *) back_loop,
  407.                                                  (gleVector *) front_norm, 
  408.                                                  (gleVector *) back_norm,
  409.                                                  inext, len_seg);
  410.             } else {
  411.                draw_binorm_segment_edge_n (ncp, (gleVector *) front_loop, 
  412.                                                 (gleVector *) back_loop,
  413.                                                 (gleVector *) front_norm,
  414.                                                 (gleVector *) back_norm,
  415.                                                 inext, len_seg);
  416.             }
  417.          } else {
  418.             if (cont_normal == NULL) {
  419.                draw_segment_color (ncp, (gleVector *) front_loop, 
  420.                                         (gleVector *) back_loop, 
  421.                                    color_array[inext-1],
  422.                                    color_array[inext], inext, len_seg);
  423.             } else
  424.             if (__TUBE_DRAW_FACET_NORMALS) {
  425.                draw_binorm_segment_c_and_facet_n (ncp, 
  426.                                    (gleVector *) front_loop, 
  427.                                    (gleVector *) back_loop, 
  428.                                    (gleVector *) front_norm, 
  429.                                    (gleVector *) back_norm, 
  430.                                    color_array[inext-1],
  431.                                    color_array[inext], inext, len_seg);
  432.             } else {
  433.                draw_binorm_segment_c_and_edge_n (ncp, 
  434.                                    (gleVector *) front_loop, 
  435.                                    (gleVector *) back_loop, 
  436.                                    (gleVector *) front_norm, 
  437.                                    (gleVector *) back_norm, 
  438.                                    color_array[inext-1],
  439.                                    color_array[inext], inext, len_seg);
  440.              }
  441.           }
  442.       }
  443.       /* |||||||||||||||||| END SEGMENT DRAW |||||||||||||||||||| */
  444.       /* pop this matrix, do the next set */
  445.       POPMATRIX ();
  446.       /* bump everything to the next vertex */
  447.       len_seg = len;
  448.       i = inext;
  449.       inext = inextnext;
  450.       VEC_COPY (bi_0, bi_1);
  451.       /* trade norm loops */
  452.       tmp = front_norm;
  453.       front_norm = back_norm;
  454.       back_norm = tmp;
  455.       /* reflect the up vector in the bisecting plane */
  456.       VEC_REFLECT (yup, yup, bi_0);
  457.    }
  458.    /* be sure to free it all up */
  459.    free (mem_anchor);
  460. }
  461.    
  462. /* ============================================================ */