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

📄 chapter11.html

📁 OpenGl红宝书
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<P>represents a B閦ier curve as <I>u</I> varies from 0 to 1. To represent
the same curve but allowing <I>u</I> to vary between <I>u</I>1 and <I>u</I>2
instead of 0 and 1, evaluate
<P><IMG SRC="figures/eq1103.gif" ALT="[IMAGE]" NOSAVE >
<P>The command <B>glMap1()</B> defines a one-dimensional evaluator that
uses these equations.void <B>glMap1</B>{fd}(GLenum <B>target</B>, <B>TYPEu1</B>,
<B>TYPE</B><I>u2</I>, GLint <B>stride</B>, GLint <B>order</B>, <B>const
TYPE*points</B>);
<P>Defines a one-dimensional evaluator. The <B>target</B> parameter specifies
what the control points represent, as shown in Table 11-1 , and therefore
how many values need to be supplied in <B>points</B>. 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 <B>glEnable()</B> or <B>glDisable()</B>
to enable or disable the evaluator.
<P>The second two parameters for <B>glMap1*()</B>, <I>u1</I> and <I>u2</I>,
indicate the range for the variable <I>u</I>. The variable <B>stride</B>
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.
<P>The <B>order</B> is the degree plus one, and it should agree with the
number of control points. The <B>points</B> parameter points to the first
coordinate of the first control point. Using the example data structure
for <B>glMap1*()</B>, use the following for <B>points</B>:
<P>(GLfloat *)(&amp;ctlpoints[0].x)
<TABLE BORDER CELLPADDING=10 >
<CAPTION ALIGN=TOP><B>Table 11-1 : </B>Types of Control Points for Use
with glMap1*()</CAPTION>

<TR ALIGN=LEFT VALIGN=TOP>
<TH>Parameter</TH>

<TH>Meaning</TH>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_VERTEX_3</TD>

<TD><I>x, y, z</I> vertex coordinates</TD>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_VERTEX_4</TD>

<TD><I>x, y, z, w </I>vertex coordinates</TD>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_INDEX</TD>

<TD>color index</TD>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_COLOR_4</TD>

<TD>R, G, B, A</TD>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_NORMAL</TD>

<TD>normal coordinates</TD>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_TEXTURE_COORD_1</TD>

<TD><I>s</I> texture coordinates</TD>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_TEXTURE_COORD_2</TD>

<TD><I>s, t</I> texture coordinates</TD>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_TEXTURE_COORD_3</TD>

<TD><I>s, t, r</I> texture coordinates</TD>
</TR>

<TR ALIGN=LEFT VALIGN=TOP>
<TD>GL_MAP1_TEXTURE_COORD_4</TD>

<TD><I>s, t, r, q</I> texture coordinates</TD>
</TR>
</TABLE>

<BR>&nbsp;
<P>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 <B>glEvalCoord1()</B> 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.
<P>Use<B> glEvalCoord1*()</B> to evaluate a defined and enabled one-dimensional
map.void <B>glEvalCoord1</B>{fd}{v}(<B>TYPE u</B>);
<P>Causes evaluation of the enabled one-dimensional maps. The argument
<B>u</B> is the value (or a pointer to the value, in the vector version
of the command) that's the domain coordinate.
<H4>
Defining Evenly Spaced Coordinate Values in One Dimension</H4>
You can use <B>glEvalCoord1()</B> with any values for <B>u</B>, 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 <B>glMapGrid1*()</B> and then apply it using <B>glEvalMesh1()</B>.void
<B>glMapGrid1</B>{fd}(GLint <B>n</B>, <B>TYPEu1</B>, <B>TYPEu2</B>);
<P>Defines a grid that goes from <B>u1</B> to <B>u2</B> in <B>n</B> steps,
which are evenly spaced.
<P>void <B>glEvalMesh1</B>(GLenum <B>mode</B>, GLint <B>p1</B>, GLint <B>p2</B>);
<P>Applies the currently defined map grid to all enabled evaluators. The
<B>mode</B> 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 <B>glEvalCoord1()</B> for each of the steps
between and including <B>p1</B> and <B>p2</B>, where 0 &lt;= <B>p1</B>,
<B>p2</B> &lt;= <B>n</B>. Programatically, it's equivalent to the following:
<PRE>glBegin(GL_POINTS);&nbsp;&nbsp;&nbsp; /* OR glBegin(GL_LINE_STRIP); */
for (i = p1; i &lt;= p2; i++)&nbsp;
&nbsp;&nbsp;&nbsp; glEvalCoord1(u1 + i*(u2-u1)/n);
glEnd();</PRE>
except that if <B>i</B> = 0 or <B>i</B> = <B>n</B>, then <B>glEvalCoord()</B>
is called with exactly <I>u1</I> or <I>u2</I> as its parameter.
<P>
<HR>
<H3>
Two-Dimensional Evaluators</H3>
In two dimensions, everything is similar to the one-dimensional case, except
that all the commands must take two parameters, <I>u</I> and <I>v</I>,
into account. Points, colors, normals, or texture coordinates must be supplied
over a surface instead of a curve. Mathematically, the definition of a
B閦ier surface patch is given by
<P><IMG SRC="figures/eq1104.gif" ALT="[IMAGE]" NOSAVE >
<BR>&nbsp;
<BR>&nbsp;
<P>where <I>P</I>ij are a set of <I>m*n</I> control points, and the <I>B</I>i
are the same Bernstein polynomials for one dimension. As before, the <I>Pij</I>
can represent vertices, normals, colors, or texture coordinates.
<P>The procedure to use two-dimensional evaluators is similar to the procedure
for one dimension:
<OL>Define the evaluator(s) with <B>glMap2*()</B>.
<BR>&nbsp;
<P>Enable them by passing the appropriate value to <B>glEnable()</B>.
<BR>&nbsp;
<P>Invoke them either by calling <B>glEvalCoord2()</B> between a <B>glBegin()</B>
and <B>glEnd()</B> pair, or by specifying and then applying a mesh with
<B>glMapGrid2()</B> and <B>glEvalMesh2()</B>.</OL>

<H4>
Defining and Evaluating a Two-Dimensional Evaluator</H4>
Use <B>glMap2*()</B> and <B>glEvalCoord2*()</B> to define and then invoke
a two-dimensional evaluator.void <B>glMap2</B>{fd}(GLenum <B>target</B>,
<B>TYPEu1</B>, <B>TYPEu2</B>, GLint <B>ustride</B>, GLint <B>uorder</B>,
<B>TYPEv1</B>, <B>TYPEv2</B>, GLint <B>vstride</B>, GLint <B>vorder</B>,
<B>TYPE points</B>);
<P>The <B>target</B> parameter can have any of the values in Table 11-1
, except that the string MAP1 is replaced with MAP2. As before, these values
are also used with <B>glEnable()</B> to enable the corresponding evaluator.
Minimum and maximum values for both <I>u </I>and <I>v</I> are provided
as <B>u1</B>, <B>u2</B>, <B>v1</B>, and <B>v2</B>. The parameters <B>ustride</B>
and <B>vstride</B> indicate the number of single- or double-precision values
(as appropriate) between independent settings for these values allows users
to select a subrectangle of control points out of a much larger array.
For example, if the data appears in the form
<PRE>GLfloat ctlpoints[100][100][3];</PRE>
and you want to use the 4x4 subset beginning at ctlpoints[20][30], choose
<B>ustride</B> to be 100*3, and <B>vstride</B> to be 3. The starting point,
<B>points</B>, should be set to &amp;ctlpoints[20][30][0]. Finally, the
order parameters, <B>uorder</B> and <B>vorder</B>, can be different, allowing
patches that are cubic in one direction and quadratic in the other, for
example.
<P>void <B>glEvalCoord2</B>{fd}{v}(<B>TYPE u, TYPE v</B>);
<P>Causes evaluation of the enabled two-dimensional maps. The arguments
<B>u </B>and<B> v</B> are the values (or a pointer to the value, in the
vector version of the command) for the domain coordinates. If either of
the vertex evaluators is enabled (GL_MAP2_VERTEX_3 or GL_MAP2_VERTEX_4),
then the normal to the surface is computed analytically. This normal is
associated with the generated vertex if automatic normal generation has
been enabled by passing GL_AUTO_NORMAL to <B>glEnable()</B>. If it's disabled,
the corresponding enabled normal map is used to produce a normal. If no
such map exists, the current normal is used.
<H4>
Two-Dimensional Example: A B閦ier Surface</H4>
Example 11-2 draws a wireframe B閦ier surface using evaluators, as shown
in Figure 11-2 . In this example, the surface is drawn with nine curved
lines in each direction. Each curve is drawn as 30 segments. To get the
whole program, add the <B>myReshape()</B> and <B>main()</B> routines from
Example 11-1 .
<P><IMG SRC="figures/bezsurf.gif" ALT="[IMAGE]" NOSAVE >
<P><B>Figure 11-2 : </B>A B閦ier Surface
<BR>&nbsp;
<BR>&nbsp;
<P><B>Example 11-2 : </B>Drawing a B閦ier Surface: bezsurf.c
<PRE>#include &lt;GL/gl.h>
#include &lt;GL/glu.h>
#include "aux.h"

GLfloat ctrlpoints[4][4][3] = {
&nbsp;&nbsp;&nbsp; {{-1.5, -1.5, 4.0}, {-0.5, -1.5, 2.0},&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0.5, -1.5, -1.0}, {1.5, -1.5, 2.0}},&nbsp;
&nbsp;&nbsp;&nbsp; {{-1.5, -0.5, 1.0}, {-0.5, -0.5, 3.0},&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0.5, -0.5, 0.0}, {1.5, -0.5, -1.0}},&nbsp;
&nbsp;&nbsp;&nbsp; {{-1.5, 0.5, 4.0}, {-0.5, 0.5, 0.0},&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0.5, 0.5, 3.0}, {1.5, 0.5, 4.0}},&nbsp;
&nbsp;&nbsp;&nbsp; {{-1.5, 1.5, -2.0}, {-0.5, 1.5, -2.0},&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {0.5, 1.5, 0.0}, {1.5, 1.5, -1.0}}
};

void display(void)
{
&nbsp;&nbsp;&nbsp; int i, j;

&nbsp;&nbsp;&nbsp; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
&nbsp;&nbsp;&nbsp; glColor3f(1.0, 1.0, 1.0);
&nbsp;&nbsp;&nbsp; glPushMatrix ();
&nbsp;&nbsp;&nbsp; glRotatef(85.0, 1.0, 1.0, 1.0);
&nbsp;&nbsp;&nbsp; for (j = 0; j &lt;= 8; j++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glBegin(GL_LINE_STRIP);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt;= 30; i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/8.0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glEnd();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glBegin(GL_LINE_STRIP);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt;= 30; i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glEvalCoord2f((GLfloat)j/8.0, (GLfloat)i/30.0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glEnd();
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; glPopMatrix ();
&nbsp;&nbsp;&nbsp; glFlush();
}

void myinit(void)
{
&nbsp;&nbsp;&nbsp; glClearColor (0.0, 0.0, 0.0, 1.0);
&nbsp;&nbsp;&nbsp; glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0, 1, 12, 4, &amp;ctrlpoints[0][0][0]);
&nbsp;&nbsp;&nbsp; glEnable(GL_MAP2_VERTEX_3);
&nbsp;&nbsp;&nbsp; glEnable(GL_DEPTH_TEST);
&nbsp;&nbsp;&nbsp; glShadeModel(GL_FLAT);
}</PRE>

<H4>
Defining Evenly Spaced Coordinate Values in Two Dimensions</H4>
In two dimensions, the <B>glMapGrid2*()</B> and <B>glEvalMesh2()</B> commands
are similar to the one-dimensional versions, except that both <I>u</I>
and <I>v</I> information must be included.void <B>glMapGrid2</B>{fd}(GLint
<B>nu</B>, <B>TYPEu1</B>, <B>TYPEu2</B>, GLint <B>nv</B>, <B>TYPEv1</B>,
<B>TYPEv2</B>);
<BR>void <B>glEvalMesh2</B>(GLenum <B>mode</B>, GLint <B>p1</B>, GLint
<B>p2</B>, GLint <B>q2</B>, GLint <B>q2</B>);
<P>Defines a two-dimensional map grid that goes from <B>u1</B> to <B>u2</B>
in <B>nu</B> evenly spaced steps and from <B>v1</B> to <B>v2</B> in <B>nv</B>
steps (<B>glMapGrid2*()</B>), and then applies this grid to all enabled
evaluators (<B>glEvalMesh2()</B>). The only significant difference from
the one-dimensional versions of these two commands is that in <B>glEvalMesh2()</B>,
the <B>mode</B> parameter can be GL_FILL as well as GL_POINT or GL_LINE.
GL_FILL generates filled polygons using the quad-mesh primitive. Stated
precisely, <B>glEvalMesh2()</B> is nearly equivalent to one of the following
three code fragments. (It's nearly equivalent because when<B> i</B> is
equal to <B>nu</B> or <B>j</B> to <B>nv</B>, the parameter is exactly equal
to <B>u2</B> or <B>v2</B>, not to <B>u1</B><I>+</I><B>nu</B><I>*(</I><B>u2</B>-<B>u1</B><I>)/</I><B>nu</B>,
which might be slightly different due to round-off error.)
<PRE>glBegin(GL_POINTS);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* mode == GL_POINT */&nbsp;
for (i = nu1; i &lt;= nu2; i++)&nbsp;
&nbsp;&nbsp;&nbsp; for (j = nv1; j &lt;= nv2; j++)&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; glEvalCoord2(u1 + i*(u2-u1)/nu, v1+j*(v2-v1)/nv);
glEnd();</PRE>
or
<PRE>for (i = nu1; i &lt;= nu2; i++) {&nbsp;&nbsp;&nbsp;&nbsp; /* mode == GL_LINE */

⌨️ 快捷键说明

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