Open GL Super Bible

Previous Table of Contents Next


Creating a NURBS Surface

The glu NURBS functions provide a useful high-level facility for rendering surfaces. You don’t have to explicitly call the evaluators or establish the mappings or grids. To render a NURBS, you first create a NURBS object that you will reference whenever you call the NURBS-related functions to modify the appearance of the surface or curve.

The function gluNewNurbsRenderer creates a renderer for the NURB, and gluDeleteNurbsRenderer destroys it. The following code fragments demonstrate these functions in use:

// NURBS object pointer
GLUnurbsObj *pNurb = NULL;
…
…

// Setup the NURBS object
    pNurb = gluNewNurbsRenderer();

…
// Do your NURBS things…
…
…

// Delete the NURBS object if it was created
if(pNurb)
        gluDeleteNurbsRenderer(pNurb);

NURBS Properties

Once you have created a NURBS renderer, you can set various high-level NURBS properties for the NURB, like this:

// Set sampling tolerance
gluNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE, 25.0f);

// Fill to make a solid surface (use GLU_OUTLINE_POLYGON to create a
// polygon mesh)
gluNurbsProperty(pNurb, GLU_DISPLAY_MODE, (GLfloat)GLU_FILL);

You will typically call these functions in your setup routine, rather than repeatedly in your rendering code. In this example, the GLU_SAMPLING_TOLERANCE defines how fine the mesh that defines the surface is, and GLU_FILL tells OpenGL to fill in the mesh instead of generating a wireframe.

Define the Surface

The surface definition is passed as arrays of control points and knot sequences to the gluNurbsSurface function. As shown here, this function is also bracketed by calls to gluBeginSurface and gluEndSurface:

// Render the NURB
// Begin the NURB definition
gluBeginSurface(pNurb);

// Evaluate the surface
gluNurbsSurface(pNurb,      // pointer to NURBS renderer
   8, Knots,                // No. of knots and knot array u direction
   8, Knots,                // No. of knots and knot array v direction
   4 * 3,                   // Distance between control points in u dir.
   3,                       // Distance between control points in v dir.
   &ctrlPoints[0][0][0],    // Control points
   4, 4,                    // u and v order of surface
   GL_MAP2_VERTEX_3);       // Type of surface

// Done with surface
gluEndSurface(pNurb);

You can make more calls to gluNurbsSurface to create any number of NURBS surfaces, but the properties you set for the NURBS renderer will still be in effect. Often this is desired, anyway—you rarely want two surfaces (perhaps joined) to have different fill styles (one filled, and one a wire mesh).

Using the control points and knot values shown in the next code segment, we produce the NURBS surface shown in Figure 17-9. This NURBS program is found in this chapter’s subdirectory on the CD.


Figure 17-9  Output from the NURBS program

// Mesh extends four units -6 to +6 along x and y axis
// Lies in Z plane
//                 u  v  (x,y,z)
GLfloat ctrlPoints[4][4][3]= {{{  -6.0f, -6.0f, 0.0f},         // u = 0,   v = 0
                                    {    -6.0f, -2.0f, 0.0f},  //          v = 1
                                    {   -6.0f,  2.0f, 0.0f},   //          v = 2
                                    {   -6.0f,  6.0f, 0.0f}},  //          v = 3

                                   {{  -2.0f, -6.0f, 0.0f},    // u = 1    v = 0
                                    {   -2.0f, -2.0f, 8.0f},   //          v = 1
                                    {   -2.0f,  2.0f, 8.0f},   //          v = 2
                                    {   -2.0f,  6.0f, 0.0f}},  //          v = 3

                                   {{   2.0f, -6.0f, 0.0f },   // u =2     v = 0
                                    {    2.0f, -2.0f, 8.0f },  //          v = 1
                                    {    2.0f,  2.0f, 8.0f },  //          v = 2
                                    {    2.0f,  6.0f, 0.0f }}, //          v = 3

                                   {{   6.0f, -6.0f, 0.0f},    // u = 3    v = 0
                                    {    6.0f, -2.0f, 0.0f},   //          v = 1
                                    {    6.0f,  2.0f, 0.0f},   //          v = 2
                                    {    6.0f,  6.0f, 0.0f}}}; //          v = 3

// Knot sequence for the NURB
GLfloat Knots[8] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f};


Previous Table of Contents Next