The GLE Graphics Pipeline & Implementation Internals

This section is a weak attempt to document the workings of the internals of the GLE library. The GLE pipeline is implemented in four stages: converting the high-level shapes into a series of extrusions, breaking down each extrusion into individual straight segments, converting each segment into triangle strips, and applying a texture to the triangle strips. The pipeline is implemented in the following source files:

All of the high-level geometric shapes: spirals, surfaces of revolution, etc. are defined here. Essentially, all of the high-level shapes are really just utilities built on top of the basic extrusion-drawing engine, described below. In all cases, the basic extrusion can be thought of as a set of straight segments, joined together with different join styles.

ex_angle.c, ex_cut_round.c
The workhorse routines for decomposing a polyline path into a set of segments, and doing all the heavy math needed to compute the beginning and end of each segment. The easiest way to visualize what these routines do is to think of drawing a tube: a circle-ish thing extruded along a path. The simpler half of the hard math is to find the local coordinate system so that each tube segment lies along the local z-axis, where the extruded shape (i.e. the circular-ish thing) is just a contour in the x-y plane. The hard part of the math is to compute the endpoints so that the joins mitre together nicely.

Draws each 'segment' of a poly-tube, using the simplest, 'raw' joinstyle. Basically, just takes a single segment, as computed above, and draws it as a triangle strip.

As above, draws each segment as a triangle strip. Slightly generalized, so that it is suitable for use with all join styles.

Implements the texture mapping routines. In order to have a texture map 'stick' to the surface of an object, we have to pin the corners of the texture map to the corners of a triangle strip. This is a relatively easy computation. It is done as the last stage: after all of the triangle strips have been computed, and are being output. Thus, this is the last stage of the pipeline.

Defines the GLE graphics context aka graphics state. Anything that might have been a global variable storing state in between calls to GLE has been stuffed into the context structure. There is only one global variable: the pointer to the context structure. This should make it very easy to make GLE thread-safe: One needs only to take this global var, and make it per-thread (e.g. using pthread_setspecific()). No one has done so yet, send me the patch if you do.

Portability interface. In fact, GLE is not at all specific to OpenGL. You can easily (and I really do mean easily) port this library to any graphics subsystem that can draw a triangle mesh. Its not hard; you merely have to create callback routines for the half-dozen primitives. If you want to just capture the raw triangle strip data that comes out of GLE, this is again the place to look. (Although you will also want to study tube_gc.h and texgen.c a bit to understand the bottom end of the pipeline.

The remainder of the files provide various adjunct utilities:

Computes a 4x4 matrix that aligns a tube segment along the local z-axis, and so that the contour x-y axes become the local-coordinate x-y axes

Macros used to compute intersecting 'cutting' planes and bisecting planes given a set of points and vectors. These planes are used to create the various joins between tubes.

Macros to perform vector and matrix addition, multiplication, etc. These are tuned for high performance, and are expressed as macros (rather than inline functions) so that even 'stupid' compilers have a good chance at performing good optimizations.

Some OpenGL implementations can minimize Gouraud-shading artifacts by using quad-meshes instead of triangle meshes. This is an obscure feature. Look here if you need this.

Draw rounded joinstyle end-caps.

Last updated: Linas Vepstas July 2001