目 录
13.1 图元扩展
13.2 法向计算
13.3 曲线生成
13.4 曲面构造
在前面的章节中已经讲述了最基本的几何图元建模,但在实际应用中只有这些图元是很不够的,要生成一个稍微复杂点的曲线、曲面或一些不规则的物体(例如山脉等)相当费事。令人比较高兴的是,OpenGL基本库(gl库)和功能库(glu库)为我们提供了很大的方便,这一章将详细介绍图元扩展、法向计算、曲线生成和曲面构造等内容。
13.1 图元扩展
13.1.1 点和线
下面分别介绍点和线的扩展形式及用法。
1)点。OpenGL中定义的点可以有不同的尺寸,其函数形式为:
void glPointSize(GLfloat size);
设置点的宽度(以象素为单位)。参数size必须大于0.0,缺省时为1.0。
2)线。OpenGL能指定线的各种宽度和绘制不同的虚点线,如点线、虚线等。相应的函数形式如下:void glLineWidth(GLfloat width);
设置线宽(以象素为单位)。参数width必须大于0.0,缺省时为1.0。void glLineStipple(GLint factor,GLushort pattern);
设置线为当前的虚点模式。参数pattern是一系列的16位数(0或1),它重复地赋给所指定的线。其中每一位代表一个象素,且从低位开始,1表示用当前颜色绘制一个象素(或比例因子指定的个数),0表示当前不绘制,只移动一个象素位(或比例因子指定的个数)。参数factor是个比例因子,它用来拉伸pattern中的元素,即重复绘制1或移动0,比如,factor为2,则碰到1时就连续绘制2次,碰到0时连续移动2个单元。factor的大小范围限制在1到255之间。在绘制虚点线之前必须先启动一下,即调用函数glEnable(GL_LINE_STIPPLE);若不用,则调用glDisable(GL_LINE_STIPPLE)关闭。下面举出一个点线扩展应用实例:
例13-1 点线扩展应用例程(expntlin.c)#include "glos.h"
#include
#include
#include
void myinit(void);
void line2i(GLint x1,GLint y1,GLint x2,GLint y2);
void CALLBACK display(void); void myinit (void)
{
glClearColor (0 , 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void line2i(GLint x1,GLint y1,GLint x2,GLint y2)
{
glBegin(GL_LINES);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glEnd();
}
void CALLBACK display(void)
{
int i;
glClear (GL_COLOR_BUFFER_BIT);
/* 第一行绘制的是一系列大小尺寸不同的点(以象素为基本扩展单元) */
glColor3f(0.8,0.6,0.4);
for (i = 1; i <= 10; i++)
{
glPointSize(i*2);
glBegin (GL_POINTS);
glVertex2f (30.0 + ((GLfloat) i * 50.0), 330.0);
glEnd ();
}
/* 第二行绘制的是三条不同线型的线段 */
glEnable (GL_LINE_STIPPLE);
glLineStipple (1, 0x0101); /* 点线 */
glColor3f(1.0 ,0.0,0.0);
line2i (50, 250, 200, 250);
glLineStipple (1, 0x00FF); /* 虚线 */
glColor3f(1.0,1.0,0.0);
line2i (250 , 250 , 400, 250 );
glLineStipple (1, 0x1C47); /* 虚点线 */
glColor3f(0.0,1.0,0.0);
line2i (450 , 250 , 600 , 250 );
/* 第三行绘制的是三条不同宽度的线段 */
glLineWidth (5.0);
glLineStipple (1, 0x0101);
glColor3f(1.0 ,0.0,0.0);
line2i (50 , 200 , 200 , 200 );
glLineWidth (3.0);
glLineStipple (1, 0x00FF);
glColor3f(1.0 ,1.0,0.0);
line2i (250 , 200 , 400 , 200 );
glLineWidth (2.0);
glLineStipple (1, 0x1C47);
glColor3f(0.0 ,1.0,0.0);
line2i (450 , 200 , 600 , 200 );
/* 设置以下线段的宽度为 1 */
glLineWidth(1);
/* 第四行绘制的是一条虚点线 */
glLineStipple (1, 0xff0c);
glBegin (GL_LINE_STRIP);
glColor3f(0.0 ,1.0,1.0);
for (i = 0; i < 12; i++)
glVertex2f (50.0 + ((GLfloat) i * 50.0), 150.0);
glEnd ();
/* 第五行绘制的是十条独立的虚点斜线 */
glColor3f(0.4 ,0.3,0.8);
for (i = 0; i < 10; i++)
{
line2i (50 + ( i * 50), 70, 75 + ((i+1) * 50), 100);
}
/* 第六行绘制的是一条虚点线,其中线型模式每个元素被重复操作5次 */
glLineStipple (5, 0x1C47);
glColor3f(1.0 ,0.0,1.0);
line2i (50 , 25 , 600 , 25 );
glFlush ();
}
void main(void)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
auxInitPosition (0, 0, 650, 450);
auxInitWindow ("External Points and Lines");
myinit ();
auxMainLoop(display);
}以上程序运行结果是显示不同尺寸的点及不同线型和宽度的线的绘制方式。
图13-1 扩展点线
13.1.2 多边形
多边形的绘制模式包含有好几种:全填充式、轮廓点式、轮廓线式以及图案填充式。下面分别介绍相应的OpenGL函数形式。
1)多边形模式设置。其函数为: void glPolygonMode(GLenum face,GLenum mode);
控制多边形指定面的绘制模式。参数face为GL_FRONT、GL_BACK或GL_FRONT_AND_BACK;参数mode为GL_POINT、GL_LINE或GL_FILL,分别表示绘制轮廓点式多边形、轮廓线式多边形或全填充式多边形。缺省时,绘制的是正反面全填充式多边形。
2)设置图案填充式多边形。其函数为:void glPolygonStipple(const GLubyte *mask);
为当前多边形定义填充图案模式。参数mask是一个指向32x32位图的指针。与虚点线绘制的道理一样,某位为1时绘制,为0时什么也不绘。注意,在调用这个函数前,必须先启动一下,即用glEnable(GL_POLYGON_STIPPLE);不用时用glDisable(GL_POLYGON_STIPPLE)关闭。下面举出一个多边形扩展绘制实例:
例 13-2 多边形图案填充例程(polystpl.c)#include "glos.h"
#include
#include
#include
void myinit(void);
void CALLBACK display(void);
void myinit (void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void CALLBACK display(void)
{
/* 填充模式定义 (32x32) */
GLubyte pattern[]= {
0x00, 0x01, 0x80, 0x00,
0x00, 0x03, 0xc0, 0x00,
0x00, 0x07, 0xe0, 0x00,
0x00, 0x0f, 0xf0, 0x00,
0x00, 0x1f, 0xf8, 0x00,
0x00, 0x3f, 0xfc, 0x00,
0x00, 0x7f, 0xfe, 0x00,
0x00, 0xff, 0xff, 0x00,
0x01, 0xff, 0xff, 0x80,
0x03, 0xff, 0xff, 0xc0,
0x07, 0xff, 0xff, 0xe0,
0x0f, 0xff, 0xff, 0xf0,
0x1f, 0xff, 0xff, 0xf8,
0x3f, 0xff, 0xff, 0xfc,
0x7f, 0xff, 0xff, 0xfe,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xfe,
0x3f, 0xff, 0xff, 0xfc,
0x1f, 0xff, 0xff, 0xf8,
0x0f, 0xff, 0xff, 0xf0,
0x07, 0xff, 0xff, 0xe0,
0x03, 0xff, 0xff, 0xc0,
0x01, 0xff, 0xff, 0x80,
0x00, 0xff, 0xff, 0x00,
0x00, 0x7f, 0xfe, 0x00,
0x00, 0x3f, 0xfc, 0x00,
0x00, 0x1f, 0xf8, 0x00,
0x00, 0x0f, 0xf0, 0x00,
0x00, 0x07, 0xe0, 0x00,
0x00, 0x03, 0xc0, 0x00,
0x00, 0x01, 0x80, 0x00
};
glClear (GL_COLOR_BUFFER_BIT);
/* 绘制一个指定图案填充的矩形 */
glColor3f(0.1,0.8,0.7);
glEnable (GL_POLYGON_STIPPLE);
glPolygonStipple (pattern);
glRectf (48.0, 80.0, 210.0, 305.0);
/* 绘制一个指定图案填充的三角形 */
glCo