Silicon Graphics

[Prev] [TOC] [Next]



(-) OpenGL Programming Guide
(-) Chapter 11Evaluators and NURBS
(-) Evaluators

One-Dimensional Evaluators

This section presents an example of using one-dimensional evaluators to draw a curve. It then describes the commands and equations that control evaluators.

One-Dimensional Example: A Simple Bézier Curve

The program shown in Example 11-1 draws a cubic Bézier curve using four control points, as shown in Figure 11-1 .

[IMAGE]

Figure 11-1 : A Bézier Curve


Example 11-1 : Drawing a Bézier Curve Using Four Control Points: bezcurve.c

#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"

GLfloat ctrlpoints[4][3] = {
    { -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0}, 
    {2.0, -4.0, 0.0}, {4.0, 4.0, 0.0}};

void myinit(void)
{
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4,&ctrlpoints[0][0]);
    glEnable(GL_MAP1_VERTEX_3);
    glShadeModel(GL_FLAT);
}

void display(void)
{
    int i;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);
    glBegin(GL_LINE_STRIP);
        for (i = 0; i <= 30; i++) 
            glEvalCoord1f((GLfloat) i/30.0);
    glEnd();
   /* The following code displays the control points as dots. */
    glPointSize(5.0);
    glColor3f(1.0, 1.0, 0.0);
    glBegin(GL_POINTS);
        for (i = 0; i < 4; i++) 
            glVertex3fv(&ctrlpoints[i][0]);
    glEnd();
    glFlush();
}

void myReshape(GLsizei w, GLsizei h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
        glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w, 
            5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
    else
        glOrtho(-5.0*(GLfloat)w/(GLfloat)h, 
            5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}


int main(int argc, char** argv)
{
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
    auxInitPosition (0, 0, 500, 500);
    auxInitWindow (argv[0]);
    myinit();
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
}

A cubic Bézier curve is described by four control points, which appear in this example in the ctrlpoints[][] array. This array is one of the arguments to glMap1f(). All the arguments for this command are as follows:

GL_MAP1_VERTEX_3

Three-dimensional vertices are produced

0

Low value of parameter u

1

High value of parameter u

3

The number of floating-point values to advance in the data between one control point and the next

4

The order of the spline, which is the degree+1; in this case, the degree is 3 (since the curve is a cubic)

&ctrlpoints[0][0]

Pointer to the first control point's data

Note that the second and third arguments control the parameterization of the curve - as the variable u ranges from 0 to 1, the curve goes from one end to the other. The call to glEnable() enables the one-dimensional evaluator for two-dimensional vertices.

The curve is drawn in the routine display() between the glBegin() and glEnd() calls. Since the evaluator is enabled, the command glEvalCoord1f() is just like issuing a glVertex() command with coordinates that are the coordinates of a vertex on the curve corresponding to the input parameter u.

Defining and Evaluating a One-Dimensional Evaluator

The Bernstein polynomial of degree n (or order n+1) is given by

[IMAGE]

If Pi represents a set of control points (one-, two-, three-, or even four- dimensional), then the equation

[IMAGE]

represents a Bézier curve as u varies from 0 to 1. To represent the same curve but allowing u to vary between u1 and u2 instead of 0 and 1, evaluate

[IMAGE]

The command glMap1() defines a one-dimensional evaluator that uses these equations.void glMap1{fd}(GLenum target, TYPEu1, TYPEu2, GLint stride, GLint order, const TYPE*points);

Defines a one-dimensional evaluator. The target parameter specifies what the control points represent, as shown in Table 11-1 , and therefore how many values need to be supplied in points. The points can represent vertices, RGBA color data, normal vectors, or texture coordinates. Forexample, with GL_MAP1_COLOR_4, the evaluator generates color data along a curve in four-dimensional (RGBA) color space. You also use the parameter values listed in Table 11-1 to enable each defined evaluator before you invoke it. Pass the appropriate value to glEnable() or glDisable() to enable or disable the evaluator.

The second two parameters for glMap1*(), u1 and u2, indicate the range for the variable u. The variable stride is the number of single- or double-precision values (as appropriate) in each block of storage. Thus, it's an offset value between the beginning of one control point and the beginning of the next.

The order is the degree plus one, and it should agree with the number of control points. The points parameter points to the first coordinate of the first control point. Using the example data structure for glMap1*(), use the following for points:

(GLfloat *)(&ctlpoints[0].x)

ParameterMeaning

GL_MAP1_VERTEX_3

x, y, z vertex coordinates

GL_MAP1_VERTEX_4

x, y, z, w vertex coordinates

GL_MAP1_INDEX

color index

GL_MAP1_COLOR_4

R, G, B, A

GL_MAP1_NORMAL

normal coordinates

GL_MAP1_TEXTURE_COORD_1

s texture coordinates

GL_MAP1_TEXTURE_COORD_2

s, t texture coordinates

GL_MAP1_TEXTURE_COORD_3

s, t, r texture coordinates

GL_MAP1_TEXTURE_COORD_4

s, t, r, q texture coordinates

Table 11-1 : Types of Control Points for Use with glMap1*()


More than one evaluator can be evaluated at a time. If you have both a GL_MAP1_VERTEX_3 and a GL_MAP1_COLOR_4 evaluator defined and enabled, for example, then calls to glEvalCoord1() generate both a position and a color. Only one of the vertex evaluators can be enabled at a time, although you might have defined both of them. Similarly, only one of the texture evaluators can be active. Other than that, however, evaluators can be used to generate any combination of vertex, normal, color, and texture-coordinate data. If more than one evaluator of the same type is defined and enabled, the one of highest dimension is used.

Use glEvalCoord1*() to evaluate a defined and enabled one-dimensional map.void glEvalCoord1{fd}{v}(TYPE u);

Causes evaluation of the enabled one-dimensional maps. The argument u is the value (or a pointer to the value, in the vector version of the command) that's the domain coordinate.

Defining Evenly Spaced Coordinate Values in One Dimension

You can use glEvalCoord1() with any values for u, but by far the most common use is with evenly spaced values, as shown previously in Example 11-1 . To obtain evenly spaced values, define a one-dimensional grid using glMapGrid1*() and then apply it using glEvalMesh1().void glMapGrid1{fd}(GLint n, TYPEu1, TYPEu2);

Defines a grid that goes from u1 to u2 in n steps, which are evenly spaced.

void glEvalMesh1(GLenum mode, GLint p1, GLint p2);

Applies the currently defined map grid to all enabled evaluators. The mode can be either GL_POINT or GL_LINE, depending on whether you want to draw points or a connected line along the curve. The call has exactly the same effect as issuing a glEvalCoord1() for each of the steps between and including p1 and p2, where 0 <= p1, p2 <= n. Programatically, it's equivalent to the following:

glBegin(GL_POINTS);    /* OR glBegin(GL_LINE_STRIP); */
for (i = p1; i <= p2; i++)
glEvalCoord1(u1 + i*(u2-u1)/n);
glEnd();

except that if i = 0 or i = n, then glEvalCoord() is called with exactly u1 or u2 as its parameter.


[Prev] [TOC] [Next]

OpenGL Programming Guide


Maintained by Maintainer: Send e-mail to .htm">name@address.