/* * MODULE: extrude.c * * FUNCTION: * Provides code for the cylinder, cone and extrusion routines. * The cylinders/cones/etc. are built on top of general purpose * extrusions. The code that handles the general purpose extrusions * is in other modules. * * AUTHOR: * written by Linas Vepstas August/September 1991 * added polycone, February 1993 */ #include #include #include /* for the memcpy() subroutine */ #include #include "gutil.h" #include "vvector.h" #include "tube_gc.h" #include "extrude.h" #include "intersect.h" /* ============================================================ */ /* The routine below determines the type of join style that will be * used for tubing. */ void gleSetJoinStyle (int style) { INIT_GC(); extrusion_join_style = style; } int gleGetJoinStyle (void) { INIT_GC(); return (extrusion_join_style); } /* ============================================================ */ /* * draw a general purpose extrusion */ void gleSuperExtrusion (int ncp, /* number of contour points */ gleDouble contour[][2], /* 2D contour */ gleDouble cont_normal[][2], /* 2D contour normals */ gleDouble up[3], /* up vector for contour */ int npoints, /* numpoints in poly-line */ gleDouble point_array[][3], /* polyline */ float color_array[][3], /* color of polyline */ gleDouble xform_array[][2][3]) /* 2D contour xforms */ { INIT_GC(); _gle_gc -> ncp = ncp; _gle_gc -> contour = contour; _gle_gc -> cont_normal = cont_normal; _gle_gc -> up = up; _gle_gc -> npoints = npoints; _gle_gc -> point_array = point_array; _gle_gc -> color_array = color_array; _gle_gc -> xform_array = xform_array; switch (__TUBE_STYLE) { case TUBE_JN_RAW: (void) extrusion_raw_join (ncp, contour, cont_normal, up, npoints, point_array, color_array, xform_array); break; case TUBE_JN_ANGLE: (void) extrusion_angle_join (ncp, contour, cont_normal, up, npoints, point_array, color_array, xform_array); break; case TUBE_JN_CUT: case TUBE_JN_ROUND: /* This routine used for both cut and round styles */ (void) extrusion_round_or_cut_join (ncp, contour, cont_normal, up, npoints, point_array, color_array, xform_array); break; default: break; } } /* ============================================================ */ void gleExtrusion (int ncp, /* number of contour points */ gleDouble contour[][2], /* 2D contour */ gleDouble cont_normal[][2], /* 2D contour normals */ gleDouble up[3], /* up vector for contour */ int npoints, /* numpoints in poly-line */ gleDouble point_array[][3], /* polyline */ float color_array[][3]) /* color of polyline */ { gleSuperExtrusion (ncp, contour, cont_normal, up, npoints, point_array, color_array, NULL); } /* ============================================================ */ /* should really make this an adaptive algorithm ... */ #define _POLYCYL_TESS 20 void gen_polycone (int npoints, gleDouble point_array[][3], float color_array[][3], gleDouble radius, gleDouble xform_array[][2][3]) { int saved_style; gleDouble circle [_POLYCYL_TESS][2]; gleDouble norm [_POLYCYL_TESS][2]; double c, s; int i; double v21[3]; double len; gleDouble up[3]; INIT_GC(); /* this if statement forces this routine into double-duty for * both the polycone and the polycylinder routines */ if (xform_array != NULL) radius = 1.0; s = sin (2.0*M_PI/ ((double) _POLYCYL_TESS)); c = cos (2.0*M_PI/ ((double) _POLYCYL_TESS)); norm [0][0] = 1.0; norm [0][1] = 0.0; circle [0][0] = radius; circle [0][1] = 0.0; /* draw a norm using recursion relations */ for (i=1; i<_POLYCYL_TESS; i++) { norm [i][0] = norm[i-1][0] * c - norm[i-1][1] * s; norm [i][1] = norm[i-1][0] * s + norm[i-1][1] * c; circle [i][0] = radius * norm[i][0]; circle [i][1] = radius * norm[i][1]; } /* avoid degenerate vectors */ /* first, find a non-zero length segment */ i=0; FIND_NON_DEGENERATE_POINT(i,npoints,len,v21,point_array) if (i == npoints) return; /* next, check to see if this segment lies along x-axis */ if ((v21[0] == 0.0) && (v21[2] == 0.0)) { up[0] = up[1] = up[2] = 1.0; } else { up[0] = up[2] = 0.0; up[1] = 1.0; } /* save the current join style */ saved_style = extrusion_join_style; extrusion_join_style |= TUBE_CONTOUR_CLOSED; /* if lighting is not turned on, don't send normals. * MMODE is a good indicator of whether lighting is active */ if (!__IS_LIGHTING_ON) { gleSuperExtrusion (_POLYCYL_TESS, circle, NULL, up, npoints, point_array, color_array, xform_array); } else { gleSuperExtrusion (_POLYCYL_TESS, circle, norm, up, npoints, point_array, color_array, xform_array); } /* restore the join style */ extrusion_join_style = saved_style; } /* ============================================================ */ void glePolyCylinder (int npoints, gleDouble point_array[][3], float color_array[][3], gleDouble radius) { gen_polycone (npoints, point_array, color_array, radius, NULL); } /* ============================================================ */ void glePolyCone (int npoints, gleDouble point_array[][3], float color_array[][3], gleDouble radius_array[]) { gleAffine * xforms; int j; /* build 2D affine matrices from radius array */ xforms = (gleAffine *) malloc (npoints * sizeof(gleAffine)); for (j=0; jinf) (1+x/N) ** N * and take N=32. */ /* initialize translation and delta translation */ deltaTrans[0] = delta * dXformdTheta[0][2]; deltaTrans[1] = delta * dXformdTheta[1][2]; trans[0] = startXform[0][2]; trans[1] = startXform[1][2]; /* prepare the tangent matrix */ delta /= 32.0; mA[0][0] = 1.0 + delta * dXformdTheta[0][0]; mA[0][1] = delta * dXformdTheta[0][1]; mA[1][0] = delta * dXformdTheta[1][0]; mA[1][1] = 1.0 + delta * dXformdTheta[1][1]; /* compute exponential of matrix */ MATRIX_PRODUCT_2X2 (mB, mA, mA); /* squared */ MATRIX_PRODUCT_2X2 (mA, mB, mB); /* 4th power */ MATRIX_PRODUCT_2X2 (mB, mA, mA); /* 8th power */ MATRIX_PRODUCT_2X2 (mA, mB, mB); /* 16th power */ MATRIX_PRODUCT_2X2 (mB, mA, mA); /* 32nd power */ /* initialize running matrix */ COPY_MATRIX_2X2 (run, startXform); /* remember, the first point is hidden -- load some, any * xform for the first point */ xforms[0][0][0] = startXform[0][0]; xforms[0][0][1] = startXform[0][1]; xforms[0][0][2] = startXform[0][2]; xforms[0][1][0] = startXform[1][0]; xforms[0][1][1] = startXform[1][1]; xforms[0][1][2] = startXform[1][2]; for (i=1; i