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

GIS编程

开发平台:

Visual C++

  1. /*
  2.  * MODULE NAME: ex_raw.c
  3.  *
  4.  * FUNCTION: 
  5.  * This module contains code that draws extrusions with square
  6.  * ("raw join style") end styles.  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 <stdio.h>      /* to get stderr defined */
  20. #include <GL/tube.h>
  21. #include "port.h"
  22. #include "gutil.h"
  23. #include "vvector.h"
  24. #include "tube_gc.h"
  25. #include "extrude.h"
  26. #include "intersect.h"
  27. #include "segment.h"
  28. /* ============================================================ */
  29. /* 
  30.  * The following routine is, in principle, very simple:
  31.  * all that it does is normalize the up vector, and makes
  32.  * sure that it is perpendicular to the initial polyline segment.
  33.  *
  34.  * In fact, this routine gets awfully complicated because:
  35.  * a) the first few segements of the polyline might be degenerate, 
  36.  * b) up vecotr may be parallel to first few segments of polyline,
  37.  * c) etc.
  38.  *
  39.  */
  40. void up_sanity_check (gleDouble up[3], /* up vector for contour */
  41.                       int npoints, /* numpoints in poly-line */
  42.                       gleDouble point_array[][3]) /* polyline */
  43. {
  44.    int i;
  45.    double len;
  46.    double diff[3];
  47.    /* now, right off the bat, we should make sure that the up vector 
  48.     * is in fact perpendicular to the polyline direction */
  49.    VEC_DIFF (diff, point_array[1], point_array[0]);
  50.    VEC_LENGTH (len, diff);
  51.    if (len == 0.0) {
  52.       /* This error message should go through "official" error interface */
  53. /*
  54.       fprintf (stderr, "Extrusion: Warning: initial segment zero length n");
  55. */
  56.       /* loop till we find something that ain't of zero length */
  57.       for (i=1; i<npoints-2; i++) {
  58.          VEC_DIFF (diff, point_array[i+1], point_array[i]);
  59.          VEC_LENGTH (len, diff);
  60.          if (len != 0.0) break;
  61.       }
  62.    }
  63.    /* normalize diff to be of unit length */
  64.    len = 1.0 / len;
  65.    VEC_SCALE (diff, len, diff);
  66.    /* we want to take only perpendicular component of up w.r.t. the
  67.     * initial segment */
  68.    VEC_PERP (up, up, diff);
  69.    VEC_LENGTH (len, up);
  70.    if (len == 0.0) {
  71.       /* This error message should go through "official" error interface */
  72.       fprintf (stderr, "Extrusion: Warning: ");
  73.       fprintf (stderr, "contour up vector parallel to tubing direction n");
  74.       /* do like the error message says ... */
  75.       VEC_COPY (up, diff);
  76.    }
  77. }
  78. /* ============================================================ */
  79. /* 
  80.  * This routine does what it says: It draws the end-caps for the
  81.  * "raw" join style.
  82.  */
  83. void draw_raw_style_end_cap (int ncp, /* number of contour points */
  84.                              gleDouble contour[][2], /* 2D contour */
  85.                              gleDouble zval, /* where to draw cap */
  86.                              int frontwards) /* front or back cap */
  87. {
  88.    int j;
  89. #ifdef OPENGL_10
  90.    GLUtriangulatorObj *tobj;
  91.    double *pts;
  92. #endif /* OPENGL_10 */
  93. #ifdef GL_32
  94.    /* old-style gl handles concave polygons no problem, so the code is
  95.     * simple.  New-style gl is a lot more tricky. */
  96.    point [2] = zval;
  97.    BGNPOLYGON ();
  98.       /* draw the loop counter clockwise for the front cap */
  99.       if (frontwards) {
  100.          for (j=0; j<ncp; j++) {
  101.             point [0] = contour[j][0];
  102.             point [1] = contour[j][1];
  103.             V3F (point, j, FRONT_CAP);
  104.          }
  105.       } else {
  106.          /* the sense of the loop is reversed for backfacing culling */
  107.          for (j=ncp-1; j>-1; j--) {
  108.             point [0] = contour[j][0];
  109.             point [1] = contour[j][1];
  110.             V3F (point, j, BACK_CAP);
  111.          }
  112.       }
  113.    ENDPOLYGON ();
  114. #endif /* GL_32 */
  115. #ifdef OPENGL_10
  116.    /* malloc the @#$%^&* array that OpenGL wants ! */
  117.    pts = (double *) malloc (3*ncp*sizeof(double));
  118.    tobj = gluNewTess ();
  119.    gluTessCallback (tobj, GLU_BEGIN, glBegin);
  120.    gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
  121.    gluTessCallback (tobj, GLU_END, glEnd);
  122.    gluBeginPolygon (tobj);
  123.       /* draw the loop counter clockwise for the front cap */
  124.       if (frontwards) {
  125.          for (j=1; j<ncp; j++) {
  126.             pts [3*j] = contour[j][0];
  127.             pts [3*j+1] = contour[j][1];
  128.             pts [3*j+2] = zval;
  129.             gluTessVertex (tobj, &pts[3*j], &pts[3*j]);
  130.          }
  131.       } else {
  132.          /* the sense of the loop is reversed for backfacing culling */
  133.          for (j=ncp-2; j>-1; j--) {
  134.             pts [3*j] = contour[j][0];
  135.             pts [3*j+1] = contour[j][1];
  136.             pts [3*j+2] = zval;
  137.             gluTessVertex (tobj, &pts[3*j], &pts[3*j]);
  138.          }
  139.       }
  140.    gluEndPolygon (tobj);
  141.    free (pts);
  142.    gluDeleteTess (tobj);
  143. #endif /* OPENGL_10 */
  144. }
  145. /* ============================================================ */
  146. /* This routine does what it says: It draws a counter-clockwise cap 
  147.  * from a 3D contour loop list
  148.  */
  149. void draw_front_contour_cap (int ncp, /* number of contour points */
  150.                              gleDouble contour[][3]) /* 3D contour */
  151. {
  152.    int j;
  153. #ifdef OPENGL_10
  154.    GLUtriangulatorObj *tobj;
  155. #endif /* OPENGL_10 */
  156. #ifdef GL_32
  157.    /* old-style gl handles concave polygons no problem, so the code is
  158.     * simple.  New-style gl is a lot more tricky. */
  159.    /* draw the end cap */
  160.    BGNPOLYGON ();
  161.    for (j=0; j<ncp; j++) {
  162.       V3F (contour[j], j, FRONT_CAP);
  163.    }
  164.    ENDPOLYGON ();
  165. #endif /* GL_32 */
  166. #ifdef OPENGL_10
  167.    tobj = gluNewTess ();
  168.    gluTessCallback (tobj, GLU_BEGIN, glBegin);
  169.    gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
  170.    gluTessCallback (tobj, GLU_END, glEnd);
  171.    gluBeginPolygon (tobj);
  172.    for (j=0; j<ncp; j++) {
  173.       gluTessVertex (tobj, contour[j], contour[j]);
  174.    }
  175.    gluEndPolygon (tobj);
  176.    gluDeleteTess (tobj);
  177. #endif /* OPENGL_10 */
  178. }
  179. /* ============================================================ */
  180. /* This routine does what it says: It draws a clockwise cap 
  181.  * from a 3D contour loop list
  182.  */
  183. void draw_back_contour_cap (int ncp, /* number of contour points */
  184.                              gleDouble contour[][3]) /* 3D contour */
  185. {
  186.    int j;
  187. #ifdef OPENGL_10
  188.    GLUtriangulatorObj *tobj;
  189. #endif /* OPENGL_10 */
  190. #ifdef GL_32
  191.    /* old-style gl handles concave polygons no problem, so the code is
  192.     * simple.  New-style gl is a lot more tricky. */
  193.    /* draw the end cap */
  194.    /* draw the loop clockwise for the back cap */
  195.    /* the sense of the loop is reversed for backfacing culling */
  196.    BGNPOLYGON ();
  197.    for (j=ncp-1; j>-1; j--) {
  198.       V3F (contour[j], j, BACK_CAP);
  199.    }
  200.    ENDPOLYGON ();
  201. #endif /* GL_32 */
  202. #ifdef OPENGL_10
  203.    tobj = gluNewTess ();
  204.    gluTessCallback (tobj, GLU_BEGIN, glBegin);
  205.    gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
  206.    gluTessCallback (tobj, GLU_END, glEnd);
  207.    gluBeginPolygon (tobj);
  208.    /* draw the end cap */
  209.    /* draw the loop clockwise for the back cap */
  210.    /* the sense of the loop is reversed for backfacing culling */
  211.    for (j=ncp-1; j>-1; j--) {
  212.       gluTessVertex (tobj, contour[j], contour[j]);
  213.    }
  214.    gluEndPolygon (tobj);
  215.    gluDeleteTess (tobj);
  216. #endif /* OPENGL_10 */
  217. }
  218. /* ============================================================ */
  219. /* This routine draws a segment of raw-join-style tubing.
  220.  * Essentially, we assume that the proper transformations have already 
  221.  * been performed to properly orient the tube segment -- our only task
  222.  * left is to render */
  223. /* PLAIN - NO COLOR, NO NORMAL */
  224. void draw_raw_segment_plain (int ncp, /* number of contour points */
  225.                              gleDouble contour[][2], /* 2D contour */
  226.                              gleDouble len,
  227.                              int inext)
  228. {
  229.    int j;
  230.    double point[3]; 
  231.    /* draw the tube segment */
  232.    BGNTMESH (inext, len);
  233.    for (j=0; j<ncp; j++) {
  234.       point [0] = contour[j][0];
  235.       point [1] = contour[j][1];
  236.       point [2] = 0.0;
  237.       V3F (point, j, FRONT);
  238.       point [2] = - len;
  239.       V3F (point, j, BACK);
  240.    }
  241.    if (__TUBE_CLOSE_CONTOUR) {
  242.       /* connect back up to first point of contour */
  243.       point [0] = contour[0][0];
  244.       point [1] = contour[0][1];
  245.       point [2] = 0.0;
  246.       V3F (point, 0, FRONT);
  247.    
  248.       point [2] = - len;
  249.       V3F (point, 0, BACK);
  250.    }
  251.    ENDTMESH ();
  252.    /* draw the endcaps, if the join style calls for it */
  253.    if (__TUBE_DRAW_CAP) {
  254.       /* draw the front cap */
  255.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  256.       /* draw the back cap */
  257.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  258.    }
  259. }
  260. /* ============================================================ */
  261. /* This routine draws a segment of raw-join-style tubing.
  262.  * Essentially, we assume that the proper transformations have already 
  263.  * been performed to properly orient the tube segment -- our only task
  264.  * left is to render */
  265. /* COLOR -- DRAW ONLY COLOR */
  266. void draw_raw_segment_color (int ncp, /* number of contour points */
  267.                              gleDouble contour[][2], /* 2D contour */
  268.                              float color_array[][3], /* color of polyline */
  269.                              gleDouble len,
  270.                              int inext)
  271. {
  272.    int j;
  273.    double point[3]; 
  274.    /* draw the tube segment */
  275.    BGNTMESH (inext, len);
  276.    for (j=0; j<ncp; j++) {
  277.       point [0] = contour[j][0];
  278.       point [1] = contour[j][1];
  279.       point [2] = 0.0;
  280.       C3F (color_array[inext-1]);
  281.       V3F (point, j, FRONT);
  282.       point [2] = - len;
  283.       C3F (color_array[inext]);
  284.       V3F (point, j, BACK);
  285.    }
  286.    if (__TUBE_CLOSE_CONTOUR) {
  287.       /* connect back up to first point of contour */
  288.       point [0] = contour[0][0];
  289.       point [1] = contour[0][1];
  290.       point [2] = 0.0;
  291.    
  292.       C3F (color_array[inext-1]);
  293.       V3F (point, 0, FRONT);
  294.    
  295.       point [2] = - len;
  296.       C3F (color_array[inext]);
  297.       V3F (point, 0, BACK);
  298.    }
  299.    ENDTMESH ();
  300.    /* draw the endcaps, if the join style calls for it */
  301.    if (__TUBE_DRAW_CAP) {
  302.       /* draw the front cap */
  303.       C3F (color_array[inext-1]);
  304.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  305.       /* draw the back cap */
  306.       C3F (color_array[inext]);
  307.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  308.    }
  309. }
  310. /* ============================================================ */
  311. /* This routine draws a segment of raw-join-style tubing.
  312.  * Essentially, we assume that the proper transformations have already 
  313.  * been performed to properly orient the tube segment -- our only task
  314.  * left is to render */
  315. /* EDGE_N -- DRAW ONLY EDGE NORMALS */
  316. void draw_raw_segment_edge_n (int ncp, /* number of contour points */
  317.                              gleDouble contour[][2], /* 2D contour */
  318.                              gleDouble cont_normal[][2],/* 2D normal vecs */
  319.                              gleDouble len,
  320.                              int inext)
  321. {
  322.    int j;
  323.    double point[3]; 
  324.    double norm[3]; 
  325.    /* draw the tube segment */
  326.    norm [2] = 0.0;
  327.    BGNTMESH (inext, len);
  328.    for (j=0; j<ncp; j++) {
  329.       norm [0] = cont_normal[j][0];
  330.       norm [1] = cont_normal[j][1];
  331.       N3F (norm);
  332.       point [0] = contour[j][0];
  333.       point [1] = contour[j][1];
  334.       point [2] = 0.0;
  335.       V3F (point, j, FRONT);
  336.       point [2] = - len;
  337.       V3F (point, j, BACK);
  338.    }
  339.    if (__TUBE_CLOSE_CONTOUR) {
  340.       /* connect back up to first point of contour */
  341.       norm [0] = cont_normal[0][0];
  342.       norm [1] = cont_normal[0][1];
  343.       norm [2] = 0.0;
  344.       N3F (norm);
  345.    
  346.       point [0] = contour[0][0];
  347.       point [1] = contour[0][1];
  348.       point [2] = 0.0;
  349.       V3F (point, 0, FRONT);
  350.    
  351.       point [2] = - len;
  352.       V3F (point, 0, BACK);
  353.    }
  354.    ENDTMESH ();
  355.    /* draw the endcaps, if the join style calls for it */
  356.    if (__TUBE_DRAW_CAP) {
  357.       /* draw the front cap */
  358.       norm [0] = norm [1] = 0.0;
  359.       norm [2] = 1.0;
  360.       N3F (norm);
  361.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  362.       /* draw the back cap */
  363.       norm [2] = -1.0;
  364.       N3F (norm);
  365.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  366.    }
  367. }
  368. /* ============================================================ */
  369. /* This routine draws a segment of raw-join-style tubing.
  370.  * Essentially, we assume that the proper transformations have already 
  371.  * been performed to properly orient the tube segment -- our only task
  372.  * left is to render */
  373. /* C_AND_EDGE_N -- DRAW EDGE NORMALS AND COLORS */
  374. void draw_raw_segment_c_and_edge_n (int ncp, /* number of contour points */
  375.                              gleDouble contour[][2], /* 2D contour */
  376.                              float color_array[][3], /* color of polyline */
  377.                              gleDouble cont_normal[][2],/* 2D normal vecs */
  378.                              gleDouble len,
  379.                              int inext)
  380. {
  381.    int j;
  382.    double point[3]; 
  383.    double norm[3];
  384.    /* draw the tube segment */
  385.    norm [2] = 0.0;
  386.    BGNTMESH (inext, len);
  387.    for (j=0; j<ncp; j++) {
  388.       C3F (color_array[inext-1]);
  389.       norm [0] = cont_normal[j][0];
  390.       norm [1] = cont_normal[j][1];
  391.       N3F (norm);
  392.       point [0] = contour[j][0];
  393.       point [1] = contour[j][1];
  394.       point [2] = 0.0;
  395.       V3F (point, j, FRONT);
  396.       C3F (color_array[inext]);
  397.       N3F (norm);
  398.       point [2] = - len;
  399.       V3F (point, j, BACK);
  400.    }
  401.    if (__TUBE_CLOSE_CONTOUR) {
  402.       /* connect back up to first point of contour */
  403.       C3F (color_array[inext-1]);
  404.    
  405.       norm [0] = cont_normal[0][0];
  406.       norm [1] = cont_normal[0][1];
  407.       N3F (norm);
  408.    
  409.       point [0] = contour[0][0];
  410.       point [1] = contour[0][1];
  411.       point [2] = 0.0;
  412.       V3F (point, 0, FRONT);
  413.       
  414.    
  415.       C3F (color_array[inext]);
  416.       norm [0] = cont_normal[0][0];
  417.       norm [1] = cont_normal[0][1];
  418.       N3F (norm);
  419.    
  420.       point [2] = - len;
  421.       V3F (point, 0, BACK);
  422.    }
  423.    ENDTMESH ();
  424.    /* draw the endcaps, if the join style calls for it */
  425.    if (__TUBE_DRAW_CAP) {
  426.       /* draw the front cap */
  427.       C3F (color_array[inext-1]);
  428.       norm [0] = norm [1] = 0.0;
  429.       norm [2] = 1.0;
  430.       N3F (norm);
  431.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  432.       /* draw the back cap */
  433.       C3F (color_array[inext]);
  434.       norm [2] = -1.0;
  435.       N3F (norm);
  436.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  437.    }
  438. }
  439. /* ============================================================ */
  440. /* This routine draws a segment of raw-join-style tubing.
  441.  * Essentially, we assume that the proper transformations have already 
  442.  * been performed to properly orient the tube segment -- our only task
  443.  * left is to render */
  444. /* FACET_N -- DRAW ONLY FACET NORMALS */
  445. void draw_raw_segment_facet_n (int ncp, /* number of contour points */
  446.                              gleDouble contour[][2], /* 2D contour */
  447.                              gleDouble cont_normal[][2],/* 2D normal vecs */
  448.                              gleDouble len,
  449.                              int inext)
  450. {
  451.    int j;
  452.    double point[3]; 
  453.    double norm[3]; 
  454.    /* draw the tube segment */
  455.    norm [2] = 0.0;
  456.    BGNTMESH (inext, len);
  457.    for (j=0; j<ncp-1; j++) {
  458.       /* facet normals require one normal per four vertices */
  459.       norm [0] = cont_normal[j][0];
  460.       norm [1] = cont_normal[j][1];
  461.       N3F (norm);
  462.       point [0] = contour[j][0];
  463.       point [1] = contour[j][1];
  464.       point [2] = 0.0;
  465.       V3F (point, j, FRONT);
  466.       point [2] = - len;
  467.       V3F (point, j, BACK);
  468.       point [0] = contour[j+1][0];
  469.       point [1] = contour[j+1][1];
  470.       point [2] = 0.0;
  471.       V3F (point, j+1, FRONT);
  472.       point [2] = - len;
  473.       V3F (point, j+1, BACK);
  474.    }
  475.    if (__TUBE_CLOSE_CONTOUR) {
  476.       /* connect back up to first point of contour */
  477.       norm [0] = cont_normal[ncp-1][0];
  478.       norm [1] = cont_normal[ncp-1][1];
  479.       N3F (norm);
  480.    
  481.       point [0] = contour[ncp-1][0];
  482.       point [1] = contour[ncp-1][1];
  483.       point [2] = 0.0;
  484.       V3F (point, ncp-1, FRONT);
  485.    
  486.       point [2] = - len;
  487.       V3F (point, ncp-1, BACK);
  488.    
  489.       point [0] = contour[0][0];
  490.       point [1] = contour[0][1];
  491.       point [2] = 0.0;
  492.       V3F (point, 0, FRONT);
  493.    
  494.       point [2] = - len;
  495.       V3F (point, 0, BACK);
  496.    }
  497.    ENDTMESH ();
  498.    /* draw the endcaps, if the join style calls for it */
  499.    if (__TUBE_DRAW_CAP) {
  500.       /* draw the front cap */
  501.       norm [0] = norm [1] = 0.0;
  502.       norm [2] = 1.0;
  503.       N3F (norm);
  504.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  505.       /* draw the back cap */
  506.       norm [2] = -1.0;
  507.       N3F (norm);
  508.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  509.    }
  510. }
  511. /* ============================================================ */
  512. /* This routine draws a segment of raw-join-style tubing.
  513.  * Essentially, we assume that the proper transformations have already 
  514.  * been performed to properly orient the tube segment -- our only task
  515.  * left is to render */
  516. /* C_AND_FACET_N -- DRAW FACET NORMALS AND COLORS */
  517. void draw_raw_segment_c_and_facet_n (int ncp, /* number of contour points */
  518.                              gleDouble contour[][2], /* 2D contour */
  519.                              float color_array[][3], /* color of polyline */
  520.                              gleDouble cont_normal[][2],/* 2D normal vecs */
  521.                              gleDouble len,
  522.                              int inext)
  523. {
  524.    int j;
  525.    double point[3]; 
  526.    double norm[3]; 
  527.    /* draw the tube segment */
  528.    norm [2] = 0.0;
  529.    BGNTMESH (inext, len);
  530.    for (j=0; j<ncp-1; j++) {
  531.       /* facet normals require one normal per four vertices;
  532.        * However, we have to respecify normal each time at each vertex 
  533.        * so that the lighting equation gets triggered.  (V3F does NOT
  534.        * automatically trigger the lighting equations -- it only
  535.        * triggers when there is a local light) */
  536.       C3F (color_array[inext-1]);
  537.       norm [0] = cont_normal[j][0];
  538.       norm [1] = cont_normal[j][1];
  539.       N3F (norm);
  540.       point [0] = contour[j][0];
  541.       point [1] = contour[j][1];
  542.       point [2] = 0.0;
  543.       V3F (point, j, FRONT);
  544.       C3F (color_array[inext]);
  545.       N3F (norm);
  546.       point [2] = - len;
  547.       V3F (point, j, BACK);
  548.       
  549.       C3F (color_array[inext-1]);
  550.       N3F (norm);
  551.       point [0] = contour[j+1][0];
  552.       point [1] = contour[j+1][1];
  553.       point [2] = 0.0;
  554.       V3F (point, j+1, FRONT);
  555.       C3F (color_array[inext]);
  556.       N3F (norm);
  557.       point [2] = - len;
  558.       V3F (point, j+1, BACK);
  559.    }
  560.    if (__TUBE_CLOSE_CONTOUR) {
  561.       /* connect back up to first point of contour */
  562.       point [0] = contour[ncp-1][0];
  563.       point [1] = contour[ncp-1][1];
  564.       point [2] = 0.0;
  565.       C3F (color_array[inext-1]);
  566.    
  567.       norm [0] = cont_normal[ncp-1][0];
  568.       norm [1] = cont_normal[ncp-1][1];
  569.       N3F (norm);
  570.       V3F (point, ncp-1, FRONT);
  571.    
  572.       C3F (color_array[inext]);
  573.       N3F (norm);
  574.    
  575.       point [2] = - len;
  576.       V3F (point, ncp-1, BACK);
  577.    
  578.       C3F (color_array[inext-1]);
  579.    
  580.       norm [0] = cont_normal[0][0];
  581.       norm [1] = cont_normal[0][1];
  582.       N3F (norm);
  583.    
  584.       point [0] = contour[0][0];
  585.       point [1] = contour[0][1];
  586.       point [2] = 0.0;
  587.       V3F (point, 0, FRONT);
  588.    
  589.       C3F (color_array[inext]);
  590.       N3F (norm);
  591.    
  592.       point [2] = - len;
  593.       V3F (point, 0, BACK);
  594.    }
  595.    
  596.    ENDTMESH ();
  597.    /* draw the endcaps, if the join style calls for it */
  598.    if (__TUBE_DRAW_CAP) {
  599.       /* draw the front cap */
  600.       C3F (color_array[inext-1]);
  601.       norm [0] = norm [1] = 0.0;
  602.       norm [2] = 1.0;
  603.       N3F (norm);
  604.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  605.       /* draw the back cap */
  606.       C3F (color_array[inext]);
  607.       norm [2] = -1.0;
  608.       N3F (norm);
  609.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  610.    }
  611. }
  612. /* ============================================================ */
  613. /* This routine draws "raw" style extrusions.  By "raw" style, it is
  614.  * meant extrusions with square ends: ends that are cut at 90 degrees to
  615.  * the length of the extrusion.  End caps are NOT drawn, unless the end cap
  616.  * style is indicated.
  617.  */
  618. void extrusion_raw_join (int ncp, /* number of contour points */
  619.                          gleDouble contour[][2], /* 2D contour */
  620.                          gleDouble cont_normal[][2],/* 2D contour normal vecs */
  621.                          gleDouble up[3], /* up vector for contour */
  622.                          int npoints, /* numpoints in poly-line */
  623.                          gleDouble point_array[][3], /* polyline */
  624.                          float color_array[][3], /* color of polyline */
  625.                          gleDouble xform_array[][2][3])   /* 2D contour xforms */
  626. {
  627.    int i, j;
  628.    int inext;
  629.    gleDouble m[4][4];
  630.    gleDouble len;
  631.    gleDouble diff[3];
  632.    gleDouble bi_0[3]; /* bisecting plane */
  633.    gleDouble yup[3]; /* alternate up vector */
  634.    gleDouble nrmv[3];
  635.    short no_norm, no_cols, no_xform;     /*booleans */
  636.    char *mem_anchor;
  637.    gleDouble *front_loop, *back_loop;  /* countour loops */
  638.    gleDouble *front_norm, *back_norm;  /* countour loops */
  639.    gleDouble *tmp;
  640.    
  641.    nrmv[0] = nrmv[1] = 0.0;   /* used for drawing end caps */
  642.    /* use some local variables for needed booleans */
  643.    no_norm = (cont_normal == NULL);
  644.    no_cols = (color_array == NULL);
  645.    no_xform = (xform_array == NULL);
  646.    /* alloc loop arrays if needed */
  647.    if (! no_xform) {
  648.       mem_anchor = malloc (4 * ncp * 3 * sizeof(gleDouble));
  649.       front_loop = (gleDouble *) mem_anchor;
  650.       back_loop = front_loop + 3*ncp;
  651.       front_norm = back_loop + 3*ncp;
  652.       back_norm = front_norm + 3*ncp;
  653.    }
  654.    /* By definition, the contour passed in has its up vector pointing in
  655.     * the y direction */
  656.    if (up == NULL) {
  657.       yup[0] = 0.0;
  658.       yup[1] = 1.0;
  659.       yup[2] = 0.0;
  660.    } else {
  661.       VEC_COPY (yup, up);
  662.    }
  663.    /* ========== "up" vector sanity check ========== */
  664.    (void) up_sanity_check (yup, npoints, point_array);
  665.    /* ignore all segments of zero length */
  666.    i = 1;
  667.    inext = i;
  668.    FIND_NON_DEGENERATE_POINT (inext, npoints, len, diff, point_array);
  669.    /* first time through, get the loops */
  670.    if (! no_xform) {
  671.       for (j=0; j<ncp; j++) {
  672.             MAT_DOT_VEC_2X3 ((&front_loop[3*j]), 
  673.                              xform_array[inext-1], contour[j]);
  674.             front_loop[3*j+2] = 0.0;
  675.       }
  676.       if (!no_norm) {
  677.          for (j=0; j<ncp; j++) {
  678.             NORM_XFORM_2X2 ( (&front_norm[3*j]),
  679.                              xform_array[inext-1],
  680.                              cont_normal [j]);
  681.             front_norm[3*j+2] = 0.0;
  682.             back_norm[3*j+2] = 0.0;
  683.          }
  684.       }
  685.    }
  686.    /* draw tubing, not doing the first segment */
  687.    while (inext<npoints-1) {
  688.       /* get the two bisecting planes */
  689.       bisecting_plane (bi_0, point_array[i-1], 
  690.                              point_array[i], 
  691.                              point_array[inext]);
  692.       /* reflect the up vector in the bisecting plane */
  693.       VEC_REFLECT (yup, yup, bi_0);
  694.       /* rotate so that z-axis points down v2-v1 axis, 
  695.        * and so that origen is at v1 */
  696.       uviewpoint (m, point_array[i], point_array[inext], yup);
  697.       PUSHMATRIX ();
  698.       MULTMATRIX (m);
  699.       /* There are six different cases we can have for presence and/or
  700.        * absecnce of colors and normals, and for interpretation of
  701.        * normals. The blechy set of nested if statements below
  702.        * branch to each of the six cases */
  703.       if (no_xform) {
  704.          if (no_cols) {
  705.             if (no_norm) {
  706.                draw_raw_segment_plain (ncp, contour, len, inext);
  707.             } else 
  708.             if (__TUBE_DRAW_FACET_NORMALS) {
  709.                draw_raw_segment_facet_n (ncp, contour, cont_normal,
  710.                                                len, inext);
  711.             } else {
  712.                draw_raw_segment_edge_n (ncp, contour, cont_normal,
  713.                                                len, inext);
  714.             }
  715.          } else {
  716.             if (no_norm) {
  717.                draw_raw_segment_color (ncp, contour, color_array, len, inext);
  718.             } else 
  719.             if (__TUBE_DRAW_FACET_NORMALS) {
  720.                draw_raw_segment_c_and_facet_n (ncp, contour, 
  721.                                                color_array,
  722.                                                cont_normal,
  723.                                                len, inext);
  724.             } else {
  725.                draw_raw_segment_c_and_edge_n (ncp, contour, 
  726.                                               color_array,
  727.                                               cont_normal,
  728.                                               len, inext);
  729.              }
  730.           }
  731.       } else {
  732.          /* else -- there are scales and offsets to deal with */
  733.          for (j=0; j<ncp; j++) {
  734.             MAT_DOT_VEC_2X3 ((&back_loop[3*j]), 
  735.                              xform_array[inext], contour[j]);
  736.             back_loop[3*j+2] = -len;
  737.             front_loop[3*j+2] = 0.0;
  738.          }
  739.          if (!no_norm) {
  740.             for (j=0; j<ncp; j++) {
  741.                NORM_XFORM_2X2 ( (&back_norm[3*j]),
  742.                                              xform_array[inext],
  743.                                              cont_normal [j]);
  744.             }
  745.          }
  746.          if (no_cols) {
  747.             if (no_norm) {
  748.                draw_segment_plain (ncp,
  749.          (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop, inext, len);
  750.             } else
  751.             if (__TUBE_DRAW_FACET_NORMALS) {
  752.                draw_binorm_segment_facet_n (ncp, (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop, 
  753.                                                  (gleDouble (*)[3]) front_norm, (gleDouble (*)[3]) back_norm, inext, len);
  754.             } else {
  755.                draw_binorm_segment_edge_n (ncp, (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop, 
  756.                                                 (gleDouble (*)[3]) front_norm, (gleDouble (*)[3]) back_norm, inext, len);
  757.             }
  758.             if (__TUBE_DRAW_CAP) {
  759.                 nrmv[2] = 1.0; N3F (nrmv);
  760.                 draw_front_contour_cap (ncp, (gleVector *) front_loop);
  761.                 nrmv[2] = -1.0; N3F (nrmv);
  762.                 draw_back_contour_cap (ncp, (gleVector *) back_loop);
  763.             }
  764.          } else {
  765.             if (no_norm) {
  766.                draw_segment_color (ncp, (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop,
  767.                                    color_array[inext-1],
  768.                                    color_array[inext], inext, len);
  769.             } else
  770.             if (__TUBE_DRAW_FACET_NORMALS) {
  771.                draw_binorm_segment_c_and_facet_n (ncp,
  772.                                    (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop,
  773.                                    (gleDouble (*)[3]) front_norm, (gleDouble (*)[3]) back_norm,
  774.                                    color_array[inext-1],
  775.                                    color_array[inext], inext, len);
  776.             } else {
  777.                draw_binorm_segment_c_and_edge_n (ncp,
  778.                                    (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop,
  779.                                    (gleDouble (*)[3]) front_norm, (gleDouble (*)[3]) back_norm,
  780.                                    color_array[inext-1],
  781.                                    color_array[inext],
  782.    inext, len);
  783.             }
  784.             if (__TUBE_DRAW_CAP) {
  785.                 C3F (color_array[inext-1]);
  786.                 nrmv[2] = 1.0; N3F (nrmv);
  787.                 draw_front_contour_cap (ncp, (gleVector *) front_loop);
  788.                 C3F (color_array[inext]);
  789.                 nrmv[2] = -1.0; N3F (nrmv);
  790.                 draw_back_contour_cap (ncp, (gleVector *) back_loop);
  791.             }
  792.          }
  793.       }
  794.       /* pop this matrix, do the next set */
  795.       POPMATRIX ();
  796.       /* flop over transformed loops */
  797.       tmp = front_loop;
  798.       front_loop = back_loop;
  799.       back_loop = tmp;
  800.       tmp = front_norm;
  801.       front_norm = back_norm;
  802.       back_norm = tmp;
  803.       i = inext;
  804.       /* ignore all segments of zero length */
  805.       FIND_NON_DEGENERATE_POINT (inext, npoints, len, diff, point_array);
  806.    }
  807.    /* free previously allocated memory, if any */
  808.    if (!no_xform) {
  809.       free (mem_anchor);
  810.    }
  811. }
  812.    
  813. /* ============================================================ */