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
- 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