Tubing and Extrusion Fact Sheet

The libgle.a library contains a collection of routines for drawing sweeps and extrusions. A "sweep" or "extrusion" is a 2D contour (polyline) that is swept or extruded along a 3D path (polyline). For example, sweeping a circe along a straight line will generate a cylinder. Sweeping a circle along a circular path will generate a doughnut (torus).

The library also includes a set of utility routines for drawing some of the more common extruded shapes: a polycylinder, a polycone, a gneralized torus (circle swept along a helical path), a "helix" (arbitrary contour swept along a helical path) and a "lathe" (arbitrary contour swept along a helical path, with torsion used to keept the contour aligned).

The most general extrusion supported by this library allows an arbitrary 2D contour to be swept around an arbitrary 3D path. A set of normal vectors can be specified to go along with the contour; the normal vectors determine the appearence of the contour when lighting is turned on. A set of colors and affine matrices can be specified to go along with the 3D path. The colors are used to color along the path. The affine matrices are used to operate on the contour as it is swept along. If no affine matrices are specified, the contour is extruded using the mathematical concept of "parrallel translation" or "gaussian translation". If there are affine matrices, they effictively introduce a local coordinate system that makes the local space non-euclidean. (In the terms of general relativity, the affines are the local metric. I'm not fooling or showing off here -- a simplified verion of the conecpts of general relativity, as in "Einstein", really are operational here. However, since there is no time, maybe non-euclidean geometry is a better term. Also, apologies to math-heads, I made the affines 2x3 instead of 3x4 because the swept contours are 2D not 3D. This makes it easier to understand/explain for the purposes of computer graphics. The 3D version would have made the explanation harder, while bringing very little extra function/feature to any common computer graphics usage. Maybe next time ...).

Some Types

#define gleDouble double
typedef gleDouble gleAffine[2][3];

Defines for Bitwise flags

Extrusion Join Styles

TUBE_JN_RAW
Draw polycylinders, polycones, extrusions, etc. with no special treatement of the extrusion ends.

TUBE_JN_ANGLE
Draw polycylinders, polycones, extrusions, etc. by extending the different segments until they butt into each other with an angular style.

TUBE_JN_CUT
Draw polycylinders, polycones, extrusions, etc. by joining together the different segments and slicing off the joint at half the angle between the segments. A cap is drawn. Note that the slicing plane runs through the origin of the contour coordinate system. Thus, the amount of slice can be varied by offsetting the contour with respect to the origin.

Note that when two segments meet at a shallow angle, the cut join style will potentially shave off a whole lot of the contour, leading to "surprising" results...

TUBE_JN_ROUND
Joints will be rounded. Strictly speaking, the part of the joint above the oigin will be rounded. The part below the origin will come together in an angular join.

TUBE_JN_MASK
Mask bits. This can be used to mask off the bit field that defines the join style.

End Caps

TUBE_JN_CAP
If this is set, a cap will be drawn at each end of the extrusion.

Automatic Normal Vector Generation

TUBE_NORM_FACET
A normal vector is generated per facet. Useful for having an extrusion have a "faceted" look, such as when extruding a square -- each of the four sides of the square will look flat.

TUBE_NORM_EDGE
Normal vectors are generated so that they lie along edges. Useful for making anguler things look rounded under lighting. For example, when extruding a hexagon and using this flag, the hexagonal extrusion will look (more like a) smooth perfectly round cylinder, rather than a six-sided shape.

TUBE_NORM_PATH_EDGE
Normal vectors are generated so that they both lie on edges, and so that they interpolate between neighboring segments. Useful for drawing "spaghetti" -- extrusions that follow a spline path. Because the spline path must be "tesselated" into small straight segments, each segment will look straight unless this flag is set.

TUBE_NORM_MASK
A mask useful for masking out the "norm" bits.

Closed or Open Countours

TUBE_CONTOUR_CLOSED
If this bit is set, the contour will be treated as a "closed" contour, where the last point connects back up to the first. It is useful to set this flag when drawing closed shapes (such as extruded cylinders, star-shapes, I-Beams, etc. When drawing open extrusions (e.g. corrugated sheet metal), you DON'T want to set this flag.

Subroutines

This library can be compiled for GL version 3.2 or above, or for OpenGL. The names of the subroutines are different for the GL and OpenGL versions. The are:
extrusion
gleExtrusion
setjoinstyle
gleSetJoinStyle
getjoinstyle
gleGetJoinStyle
polycone
glePolyCone
polycylinder
glePolyCylinder
super_extrusion
gleSuperExtrusion
twist_extrusion
gleTwistExtrusion
spiral
gleSpiral
lathe
gleLathe
helicoid
gleHelicoid

Subroutine Descriptions

 int getjoinstyle (void);
Fetch the join style flags. This word is a bitwise OR of the flags described above.

 void setjoinstyle (int style);	/* bitwise OR of flags */
Set the join style flags. This word is a bitwise OR of the flags described above.

 void polycylinder (int npoints,		/* num points in polyline */
                   gleDouble point_array[][3],	/* polyline vertces */
                   float color_array[][3],	/* colors at polyline verts */
                   gleDouble radius);		/* radius of polycylinder */
Draw polyclinder, specified as a polyline.

Note that neither the very first segment, nor the very last segment are drawn. The first and last segments serve only to define the angle of the join at the very ends of the polyline. Thus, to draw one segment, three must be specified. To draw two segments, four must be specified, etc.

The color array may be NULL. If NULL, the current color is used. If not NULL, the glColor3f() routine is used to set the color; therefore, specifying the glColorMatrial() subroutine beore this primitive can be used to set diffuse, specular, ambient, etc. colors.

 void polycone (int npoints,	 /* numpoints in poly-line */
                   gleDouble point_array[][3],	/* polyline vertices */
                   float color_array[][3],	/* colors at polyline verts */
                   gleDouble radius_array[]); /* cone radii at polyline verts */
Draw polycone, specified as a polyline with radii.

Note that neither the very first segment, nor the very last segment are drawn. The first and last segments serve only to define the angle of the join at the very ends of the polyline. Thus, to draw one segment, three must be specified. To draw two segments, four must be specified, etc.

The color array may be NULL. If NULL, the current color is used. If not NULL, the glColor3f() routine is used to set the color; therefore, specifying the glColorMatrial() subroutine beore this primitive can be used to set diffuse, specular, ambient, etc. colors.

 void extrusion (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 vertices */
                float color_array[][3]); /* colors at polyline verts */
Extrude arbitrary 2D contour along arbitrary 3D path. The argument "contour" specifies the 2D contour to be extruded, while the argument "point_array" specifies the path alomng which to extrude. The vector "up" defines the orientation of the contour y-axis in real 3D space.

Note that neither the very first segment, nor the very last segment are drawn. The first and last segments serve only to define the angle of the join at the very ends of the polyline. Thus, to draw one segment, three must be specified. To draw two segments, four must be specified, etc.

The normal array may be NULL. If it is, normal vectors will NOT be automatically generated, and the object will look terrible when lit.

The color array may be NULL. If NULL, the current color is used. If not NULL, the glColor3f() routine is used to set the color; therefore, specifying the glColorMatrial() subroutine beore this primitive can be used to set diffuse, specular, ambient, etc. colors.

 void twist_extrusion (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 vertices */
                float color_array[][3],        /* color at polyline verts */
                gleDouble twist_array[]);   /* countour twists (in degrees) */
Extrude arbitrary 2D contour along arbitrary 3D path, specifying local rotations (twists). As the contour is extruded, it will be twisted by the amount specified in the array "twist_array". The angles are measured in degrees, and the rotation is about the origin of the contour coordiante system.

The argument "contour" specifies the 2D contour to be extruded, while the argument "point_array" specifies the path alomng which to extrude. The vector "up" defines the orientation of the contour y-axis in real 3D space.

Note that neither the very first segment, nor the very last segment are drawn. The first and last segments serve only to define the angle of the join at the very ends of the polyline. Thus, to draw one segment, three must be specified. To draw two segments, four must be specified, etc.

The normal array may be NULL. If it is, normal vectors will NOT be automatically generated, and the object will look terrible when lit.

The color array may be NULL. If NULL, the current color is used. If not NULL, the glColor3f() routine is used to set the color; therefore, specifying the glColorMatrial() subroutine beore this primitive can be used to set diffuse, specular, ambient, etc. colors.

 void super_extrusion (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 vertices */
                float color_array[][3],        /* color at polyline verts */
                gleDouble xform_array[][2][3]);   /* 2D contour xforms */
Extrude arbitrary 2D contour along arbitrary 3D path, specifying local affine transformations. As the contour is extruded, the affine will be applied to the points in the contour.

The argument "contour" specifies the 2D contour to be extruded, while the argument "point_array" specifies the path alomng which to extrude. The vector "up" defines the orientation of the contour y-axis in real 3D space.

Note that neither the very first segment, nor the very last segment are drawn. The first and last segments serve only to define the angle of the join at the very ends of the polyline. Thus, to draw one segment, three must be specified. To draw two segments, four must be specified, etc.

The normal array may be NULL. If it is, normal vectors will NOT be automatically generated, and the object will look terrible when lit.

The color array may be NULL. If NULL, the current color is used. If not NULL, the glColor3f() routine is used to set the color; therefore, specifying the glColorMatrial() subroutine beore this primitive can be used to set diffuse, specular, ambient, etc. colors.

 void spiral (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 */
             gleDouble startRadius,	/* spiral starts in x-y plane */
             gleDouble drdTheta,        /* change in radius per revolution */
             gleDouble startZ,		/* starting z value */
             gleDouble dzdTheta,        /* change in Z per revolution */
             gleDouble startXform[2][3], /* starting contour affine xform */
             gleDouble dXformdTheta[2][3], /* tangent change xform per revoln */
             gleDouble startTheta,	/* start angle in x-y plane */
             gleDouble sweepTheta);	/* degrees to spiral around */
Sweep an arbitrary contour along a helical path.

The axis of the helix lies along the modeling coordinate z-axis.

An affine transform can be applied as the contour is swept. For most ordinary usage, the affines should be given as NULL.

 void lathe (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 */
             gleDouble startRadius,	/* spiral starts in x-y plane */
             gleDouble drdTheta,        /* change in radius per revolution */
             gleDouble startZ,		/* starting z value */
             gleDouble dzdTheta,        /* change in Z per revolution */
             gleDouble startXform[2][3], /* starting contour affine xform */
             gleDouble dXformdTheta[2][3], /* tangent change xform per revoln */
             gleDouble startTheta,	/* start angle in x-y plane */
             gleDouble sweepTheta);	/* degrees to spiral around */
Sweep an arbitrary contour along a helical path. The sweep will be performed as a shear along the z-axis, so that the orientation of the contour is displaced, rather than translated, as the contour is swept.

The axis of the helix lies along the modeling coordinate z-axis.

An affine transform can be applied as the contour is swept. For most ordinary usage, the affines should be given as NULL.

 void helicoid (gleDouble rToroid, /* circle contour (torus) radius */
             gleDouble startRadius,	/* spiral starts in x-y plane */
             gleDouble drdTheta,        /* change in radius per revolution */
             gleDouble startZ,		/* starting z value */
             gleDouble dzdTheta,        /* change in Z per revolution */
             gleDouble startXform[2][3], /* starting contour affine xform */
             gleDouble dXformdTheta[2][3], /* tangent change xform per revoln */
             gleDouble startTheta,	/* start angle in x-y plane */
             gleDouble sweepTheta);	/* degrees to spiral around */
Genralized Torus. Similar to spiral, except contour is a circle.

The End

Originally developed by Linas Vepstas in 1991
Version 2.0 -- port to OpenGL, 1993
Version 2.1 -- assorted touch-ups, cleanups, etc.