⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter11.html

📁 OpenGl红宝书
💻 HTML
📖 第 1 页 / 共 4 页
字号:
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);
    init_surface();

    theNurb = gluNewNurbsRenderer();
    gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);
    gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
}

void display(void)
{
    GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
        glRotatef(330.0, 1.,0.,0.);
        glScalef (0.5, 0.5, 0.5);

        gluBeginSurface(theNurb);
        gluNurbsSurface(theNurb, 
            8, knots,
            8, knots,
            4 * 3,
            3,
            &ctlpoints[0][0][0], 
            4, 4,
            GL_MAP2_VERTEX_3);
        gluEndSurface(theNurb);

    glPopMatrix();
    glFlush();
}

void myReshape(GLsizei w, GLsizei h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective (45.0, (GLdouble)w/(GLdouble)h, 3.0, 8.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef (0.0, 0.0, -5.0);
}


int main(int argc, char** argv)
{
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
    auxInitPosition (0, 0, 500, 500);
    auxInitWindow (argv[0]);
    myinit();
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
}</PRE>
As shown in Example 11-5 , <B>gluNewNurbsRenderer()</B> returns a new NURBS
object, whose type is a pointer to a GLUnurbsObj structure. The <B>gluBeginSurface()</B>
and <B>gluEndSurface()</B> pair bracket the rendering routine, saving and
restoring the evaluator state. These three routines are summarized in Appendix
C . The more complex routines, <B>gluNurbsProperty()</B> and <B>gluNurbsSurface()</B>,
are discussed in this section. void <B>gluNurbsProperty</B>(GLUnurbsObj
*<B>nobj</B>, GLenum <B>property</B>, GLfloat <B>value</B>);
<P>Controls attributes of a NURBS object, <B>nobj</B>. The <B>property</B>
argument specifies the property and can be GLU_SAMPLING_TOLERANCE, GLU_DISPLAY_MODE,
GLU_CULLING, or GLU_AUTO_LOAD_MATRIX. The <B>value</B> argument indicates
what the property should be. Since a NURBS object is rendered as primitives,
it's sampled at different values of its parameter(s) (<B>u</B> and <B>v</B>)
and broken down into small line segments or polygons for rendering. GLU_SAMPLING_TOLERANCE
controls how often the NURBS object is sampled. The default value of 50.0
makes the largest sampled line segment or polygon edge 50.0 pixels long.
<P>The default value for GLU_DISPLAY_MODE is GLU_FILL, which causes the
surface to be rendered as polygons. If GLU_OUTLINE_POLYGON is used for
the display-mode property, the outlines of polygons are rendered. Finally,
GLU_OUTLINE_PATCH renders the outlines of patches and trimming curves (see
the next section on trimming).
<P>GLU_CULLING can speed up performance by not performing tessellation
if the NURBS object falls completely outside the viewing volume; set this
property to GL_TRUE to enable culling (the default is GL_FALSE). The GLU_AUTO_LOAD_MATRIX
property determines whether the projection matrix, modelview matrix, and
viewport are downloaded from the OpenGL server (GL_TRUE, the default),
or whether the application must supply these matrices with <B>gluLoadSamplingMatrices()</B>
(GL_FALSE).
<P>void <B>gluNurbsSurface</B> (GLUnurbsObj *<B>nobj</B>, GLint <B>uknot_count</B>,
GLfloat *<B>uknot</B>, GLint <B>vknot_count</B>, GLfloat *<B>vknot</B>,
GLint <B>u_stride</B>, GLint <B>v_stride</B>, GLfloat *<B>ctlarray</B>,
GLint <B>uorder</B>, GLint <B>vorder</B>, GLenum <B>type</B>);
<P>Describes the vertices (or surface normals or texture coordinates) of
a NURBS surface, <B>nobj</B>. Several of the values must be specified for
both <I>u</I> and <I>v</I> parametric directions, such as the knot sequences
(<B>uknot</B> and <B>vknot</B>), knot counts (<B>uknot_count</B> and <B>vknot_count</B>),
and order of the polynomial (<B>uorder</B> and <B>vorder</B>) for the NURBS
surface. Note that the number of control points isn't specified. Instead,
it's derived by determining the number of control points along each parameter
as the number of knots minus the order. Then, the number of control points
for the surface is equal to the number of control points in each parametric
direction, multiplied by one another. The <B>ctlarray</B> argument points
to an array of control points.
<P>The last parameter, <B>type</B>, is one of the two-dimensional evaluator
types. Commonly, you might use GL_MAP2_VERTEX_3 for nonrational or GL_MAP2_VERTEX_4
for rational control points, respectively. You might also use other types,
such as GL_MAP2_TEXTURE_COORD_* or GL_MAP2_NORMAL to calculate and assign
texture coordinates or surface normals.
<P>The <B>u_stride</B> and <B>v_stride</B> arguments represent the number
of floating-point values between control points in each parametric direction.
The evaluator type, as well as its order, affects the <B>u_stride</B> and
<B>v_stride</B> values. In Example 11-5 , <B>u_stride</B> is 12 (4 * 3)
because there are three coordinates for each vertex (set by GL_MAP2_VERTEX_3)
and four control points in the parametric <B>v</B> direction; <B>v_stride</B>
is 3 because each vertex had three coordinates, and <B>v</B> control points
are adjacent to one another.
<P>Drawing a NURBS curve is similar to drawing a surface, except that all
calculations are done with one parameter, <B>u</B>, rather than two. Also,
for curves, <B>gluBeginCurve()</B> and <B>gluEndCurve()</B> are the bracketing
routines. void <B>gluNurbsCurve</B> (GLUnurbsObj *<B>nobj</B>, GLint <B>uknot_count</B>,
GLfloat *<B>uknot</B>, GLint <B>u_stride</B>, GLfloat *<B>ctlarray</B>,
GLint <B>uorder</B>, GLenum <B>type</B>);
<P>Defines a NURBS curve for the object <B>nobj</B>. The arguments have
the same meaning as those for <B>gluNurbsSurface()</B>. Note that this
routine requires only one knot sequence, and one declaration of the order
of the NURBS object. If this curve is defined within a <B>gluBeginCurve()/gluEndCurve()</B>
pair, then the type can be any of the valid one-dimensional evaluator types
(such as GL_MAP1_VERTEX_3 or GL_MAP1_VERTEX_4).
<P>
<HR>
<H3>
Trimming</H3>
To create a trimmed NURBS surface with OpenGL, start as if you were creating
an untrimmed surface. After calling <B>gluBeginSurface()</B> and <B>gluNurbsSurface()</B>
but before calling <B>gluEndSurface()</B>, start a trim by calling <B>gluBeginTrim()</B>.
You can create two kinds of trimming curves, a piecewise linear curve with
<B>gluPwlCurve()</B> or a NURBS curve with <B>gluNurbsCurve()</B>. A piecewise
linear curve doesn't look like what's conventionally called a curve, because
it's a series of straight lines. A NURBS curve for trimming must lie within
the unit square of parametric (<I>u</I>,<I> v</I>) space. The type for
a NURBS trimming curve is usually GLU_MAP1_TRIM2. Less often, the type
is GLU_MAP1_TRIM3, where the curve is described in a two-dimensional homogeneous
space (<I>u', v', w</I>') by (<I>u, v</I>) = (<I>u'/w</I>', <I>v'/w</I>').
void <B>gluPwlCurve</B> (GLUnurbsObj *<B>nobj</B>, GLint <B>count</B>,
GLfloat *<B>array</B>, GLint <B>stride</B>, GLenum <B>type</B>);
<P>Describes a piecewise linear trimming curve for the NURBS object <B>nobj</B>.
There are <B>count</B> points on the curve, and they're given by <B>array</B>.
The <B>type</B> can be either GLU_MAP1_TRIM_2 (the most common) or GLU_MAP1_TRIM_3
((<I>u, v, w</I>) homogeneous parameter space). The type affects whether
<B>stride</B>, the number of floating-point values to the next vertex,
is 2 or 3.
<P>You need to consider the orientation of trimming curves - that is, whether
they're counterclockwise or clockwise - to make sure you include the desired
part of the surface. If you imagine walking along a curve, everything to
the left is included and everything to the right is trimmed away. For example,
if your trim consists of a single counterclockwise loop, everything inside
the loop is included. If the trim consists of two nonintersecting counterclockwise
loops with nonintersecting interiors, everything inside either of them
is included. If it consists of a counterclockwise loop with two clockwise
loops inside it, the trimming region has two holes in it. The outermost
trimming curve must be counterclockwise. Often, you run a trimming curve
around the entire unit square to include everything within it, which is
what you get by default by not specifying any trimming curves.
<P>Trimming curves must be closed and nonintersecting. You can combine
trimming curves, so long as the endpoints of the trimming curves meet to
form a closed curve. You can nest curves, creating islands that float in
space. Be sure to get the curve orientations right. For example, an error
results if you specify a trimming region with two counterclockwise curves,
one enclosed within another: The region between the curves is to the left
of one and to the right of the other, so it must be both included and excluded,
which is impossible. Figure 11-5 illustrates a few valid possibilities.
<P><IMG SRC="figures/fig11-5.gif" ALT="[IMAGE]" NOSAVE >
<P><B>Figure 11-5 : </B>Parametric Trimming Curves
<BR>&nbsp;
<BR>&nbsp;
<P>Figure 11-6 shows the same small hill as in Figure 11-4 , this time
with a trimming curve that's a combination of a piecewise linear curve
and a NURBS curve. The program that creates this figure is similar to that
shown in Example 11-5 ; the differences are in the routines shown in Example
11-6 .
<P><IMG SRC="figures/trim.both.gif" ALT="[IMAGE]" NOSAVE >
<P><B>Figure 11-6 : </B>A Trimmed NURBS Surface
<BR>&nbsp;
<BR>&nbsp;
<P><B>Example 11-6 : </B>Trimming a NURBS Surface: trim.c
<PRE>void myinit(void)
{
&nbsp;&nbsp;&nbsp; GLfloat mat_diffuse[] = { 0.6, 0.6, 0.6, 1.0 };
&nbsp;&nbsp;&nbsp; GLfloat mat_specular[] = { 0.9, 0.9, 0.9, 1.0 };
&nbsp;&nbsp;&nbsp; GLfloat mat_shininess[] = { 128.0 };

&nbsp;&nbsp;&nbsp; glClearColor (0.0, 0.0, 0.0, 1.0);
&nbsp;&nbsp;&nbsp; glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
&nbsp;&nbsp;&nbsp; glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
&nbsp;&nbsp;&nbsp; glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

&nbsp;&nbsp;&nbsp; glEnable(GL_LIGHTING);
&nbsp;&nbsp;&nbsp; glEnable(GL_LIGHT0);
&nbsp;&nbsp;&nbsp; glDepthFunc(GL_LEQUAL);
&nbsp;&nbsp;&nbsp; glEnable(GL_DEPTH_TEST);
&nbsp;&nbsp;&nbsp; glEnable(GL_AUTO_NORMAL);
&nbsp;&nbsp;&nbsp; glEnable(GL_NORMALIZE);

&nbsp;&nbsp;&nbsp; init_surface();

&nbsp;&nbsp;&nbsp; theNurb = gluNewNurbsRenderer();
&nbsp;&nbsp;&nbsp; gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 50.0);
&nbsp;&nbsp;&nbsp; gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
}

void display(void)
{
&nbsp;&nbsp;&nbsp; GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
&nbsp;&nbsp;&nbsp; GLfloat edgePt[5][2] = /* counter clockwise */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0},&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0.0, 0.0}};
&nbsp;&nbsp;&nbsp; GLfloat curvePt[4][2] = /* clockwise */&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {{0.25, 0.5}, {0.25, 0.75}, {0.75, 0.75}, {0.75, 0.5}};
&nbsp;&nbsp;&nbsp; GLfloat curveKnots[8] =&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
&nbsp;&nbsp;&nbsp; GLfloat pwlPt[4][2] = /* clockwise */&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {{0.75, 0.5}, {0.5, 0.25}, {0.25, 0.5}};

&nbsp;&nbsp;&nbsp; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
&nbsp;&nbsp;&nbsp; glPushMatrix();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glRotatef(330.0, 1.,0.,0.);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glScalef (0.5, 0.5, 0.5);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluBeginSurface(theNurb);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluNurbsSurface(theNurb,&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8, knots,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8, knots,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4 * 3,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;ctlpoints[0][0][0],&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4, 4,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GL_MAP2_VERTEX_3);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluBeginTrim (theNurb);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluPwlCurve(theNurb, 5, &amp;edgePt[0][0], 2,&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GLU_MAP1_TRIM_2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluEndTrim (theNurb);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluBeginTrim (theNurb);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluNurbsCurve(theNurb, 8, curveKnots, 2,&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;curvePt[0][0], 4, GLU_MAP1_TRIM_2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluPwlCurve (theNurb, 3, &amp;pwlPt[0][0], 2,&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GLU_MAP1_TRIM_2);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluEndTrim (theNurb);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gluEndSurface(theNurb);

&nbsp;&nbsp;&nbsp; glPopMatrix();
&nbsp;&nbsp;&nbsp; glFlush();
}</PRE>
In Example 11-6 , <B>gluBeginTrim()</B> and <B>gluEndTrim()</B> bracket
each trimming curve. The first trim, with vertices defined by the array
<B>edgePt[][]</B>, goes counterclockwise around the entire unit square
of parametric space. This ensures that everything is drawn, provided it
isn't removed by a clockwise trimming curve inside of it. The second trim
is a combination of a NURBS trimming curve and a piecewise linear trimming
curve. The NURBS curve ends at the points (0.9, 0.5) and (0.1, 0.5), where
it is met by the piecewise linear curve, forming a closed clockwise curve.
<P>
<HR><A HREF="chapter10.html">[Previous chapter]</A> <A HREF="chapter12.html">[Next
chapter]
<HR></A>See the <A HREF="about.html">About</A> page for copyright, authoring
and distribution information.
</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -