三维曲面的呈现研究――基于VC++ OpenGL

时间:2022-06-01 01:43:14

三维曲面的呈现研究――基于VC++ OpenGL

(华中师范大学 信息技术系,湖北 武汉 430079)

摘要:OpenGL是性能卓越的图形处理工具,能够灵活地生成各种曲线和曲面,并进行曲线和曲面的呈现。但在大量数据量存在的条件下,要实时显示三维曲面是较困难的。该文对OpenGL三维曲面的呈现原理进行分析,并提出采用双缓存机制和消隐技术等可以提高图形绘制速度和刷新速度,从而将图形实时显示。

关键词:曲面构造;坐标变换;双缓存;消隐;实时显示

中图分类号:TP311文献标识码:A文章编号:1009-3044(2009)28-8047-03

Study of Three-dimensional Surface Rendering Based on VC++ OpenGL

YANG Hui

(Department of Information Technology, Huazhong Normal University, Wuhan 430079, China)

Abstract: OpenGL is a high performance graphics processing tools which can flexibly generate a variety of curves and surfaces, and for rendering curves and surfaces. However, under the condition of large amounts of data’s existence, it’s difficult to display three-dimensional surface in real-time.This paper analyzed the principles of three-dimensional surface rendering,and applied the double-buffering mechanism and blanking technique to improve the graphics rendering speed and refresh rate, thus it will graph and display in real-time.

Key words: generation of surfaces; coordinate transformation; double-buffering; blanking technique; real-time display

OpenGL是性能卓越的图形处理工具,利用OpenGL可以灵活地生成各种曲线和曲面,并将三维曲面呈现到二维的屏幕上。

1 基于OpenGL三维图形显示原理

OpenGL将三维图形通过顶点序列或是像素点进行描述,并进行透视、光照等操作,最终转换成缓存区中的图像数据,利用该数据进行着色,然后输出。OpenGL将三维曲面显示到二维屏幕的主要步骤可归纳为:

1) 构造三维曲面绘制模型:选用插值方法,构造参数曲面函数,计算控制点,进行曲面的构造。

2) 选择视点和透视方式,初步确定要呈现到二维屏幕上的投影图。

3) 利用消隐技术,进一步确定投影图中哪些线或面是可见的,哪些是不可见的,使投影图具有立体感。

4) 绘制图形,并输出。

2 基于OpenGL三维曲面的构造

OpenGL通过一种求值器的机制来产生曲线和曲面[1],该机制可以灵活生成各种曲线和曲面,并且求值器能在任何度的曲线及曲面上计算指定数目的点。然后OpenGL利用曲线和曲面上的点生成标准OpenGL图元。

对于曲线,OpenGL中使用glMap1*()函数来创建一维求值器,该函数原型及各参数含义如下:

void glMap1(

GLenum target,// 指定的控制点;

TYPE u1,TYPE u2,// u1、u2定义参数u的范围,通常为0―1;

GLint stride, //跨度,即两个控制点间的偏移量;

GLint order, //阶数;

const TYPE *points// points指针可以指向控制点集

)

求值器定义后必须要启动求值器,启动函数是glEnable(GLenum targe),参数targe与glMap1*()的第一个参数一致。一旦启动求值器后,就可以构造近似曲线。通过调用计算坐标函数glEvalcoord1*( TYPE u)替换所有对函数glVertex*()的调用,与glVertex*()使用二维、三维和四维坐标不同,glEvalcoord1*()将u值传给已启动的求值器,由求值器生成曲线坐标。U值是定义域内的任意值,glEvalcoord1*()每次调用只产生一个坐标,可以进行N次调用。

对于曲面的生成,方法与曲线生成相同。不同的是曲面使用二维求值器,并且把控制点连接起来形成一个网格。二维求值器除了使用二个参数U、V之外,其余与一维求值器基本相同。在OpenGL中定义二维求值器的函数是:

void glMap2{fd}(GLenum target,

TYPE u1,TYPE u2,

GLint ustride,GLint uorder,

TYPE v1, TYPE v2,

GLint vstride,GLint vorder,

TYPE points);

计算坐标函数为void glEvalCoord2*(TYPE u,TYPE v); 调用只产生一个坐标,可以进行N次调用。因此,我们可以基于VC++ OpenGL进行三维曲面的构造。

3三维曲面在二维屏幕上的呈现

三位曲面构造好后,需要呈现到二维屏幕上。OpenGL中,三维图形呈现到二维屏幕上的核心是OpenGL坐标系中坐标的变换[2],实质是如何将三维坐标转换为二维的屏幕坐标。

在OpenGL中,有四个坐标系:物体坐标系,即物体自身的坐标系;世界坐标系,即整个场景的最大坐标系,其它坐标系参考它而建立;观察坐标系,即摄像机坐标系,和观察者相关;屏幕坐标系,即显示屏幕的坐标系。它们之间坐标变换的顺序如下:

OpenGL 实现物体坐标系到观察坐标系的转换,即选择透视变换是通过函数glMatrixMode(GL_PROJECTION);来实现的。PROJECTION变换设置一个投影,有两个目的:一是确定三维物体在显示时哪些对象可见,哪些不可见;二是可见对象上的某个特定位置的图像在投影平面中的位置。OpenGL是通过定义一个裁剪体来达到投影的这两个目的,即在裁剪体内的对象可见,裁剪体外的对象不可见。裁剪体有两种定义,分别对应于透视投影和正交投影。透视投影的函数为:gluPerspective(angle,aspect,near,far)或者glFrustum(left,right,bottom,top,near,far)。

在本例三维曲面的呈现中,采用的是正交投影,函数为:glOrtho(left,right,bottom,top,near,far),其中(left,bottom)为前裁剪面左下角,(right,top)为前裁剪面右上角,near为前裁剪面,far后裁剪面。如图2所示。

物体坐标转换为观察坐标后,把裁剪坐标映射到窗口平面,即进行Viewport变换。OpenGL中使用函数glViewport(x,y,w,h)实现,其中(x,y)是视口左下角在屏幕上的坐标,(w,h)是视口的长和宽。

由此,把三维曲面经过一系列坐标变换转换到了二维的屏幕坐标上。

4 利用双缓冲机制和消隐技术实现实时显示

图形显示设备在显示图形时会以固定频率重绘或刷新,每一次重绘都要获取颜色缓存中的数据,并用这些值来决定屏幕上图形颜色。但是获取缓存中的数据和显示是不同步的,这样在数据量较大的时候,会使显示结果是多次执行结果的混合。在OpenGL中利用双缓存技术[3],即使用两个颜色缓存,前台缓存显示,后台缓存则是应用程序进行获取数据,绘制计算的地方。后台绘制好后,仅交换两个缓存的结果。OpenGL中使用glutSwapBuffers()实现双缓存。并且在程序初始化阶段请求双缓冲模式:glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB)。这样可以保证观察者能看到完整、准确的三维曲面,而不是曲面的绘制过程。

当三维图形在显示的时候,对象的背面信息有时不可见,对于不可见信息,可以不需考虑,从而加快显示速度。OpenGL中一般使用Z缓冲算法实现消隐。即在渲染物体时,每一个所生成像素的深度(即Z坐标)保存在一个缓冲区中,当另外一个物体也在此像素生成像素时,比较两者的深度,保留较近物体的深度到深度缓冲区。在利用OpenGL绘图时,先申请深度缓存glutInitDisplayMode(GLUT_DEPTH),然后启用glEnable (GL_DEPTH_TEST)。消隐技术在进行图形颜色填充时,加快了绘图速度。

5 实例分析:三维曲面的生成与呈现

本实例基于VC++平台,利用OpenGL生成曲线。

程序主框架:

/* 给定四个控制点坐标 */

GLfloat ctrlpoints[4][4][3] = {

{{-1.5, -1.5, 2.0}, {-0.5, -1.5, 2.0},

{0.5,-1.5,-1.0},{1.5,-1.5,2.0}},

……..

};

/*绘制Bezier曲面*/

void display(void)

{……..

for (j = 0; j

{

glBegin(GL_LINE_STRIP);

for (i = 0; i

glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/8.0);// 调用计算坐标函数

glEnd();

glBegin(GL_LINE_STRIP);

for (i = 0; i

glEvalCoord2f((GLfloat)j/8.0,(GLfloat)i/30.0);// 调用计算坐标函数

glEnd();

}

……

glutSwapBuffers();//启用双缓存

}

void init()

{…….

glEnable (GL_DEPTH_TEST);//启用Z缓冲

glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12,

4, &ctrlpoints[0][0][0]);//定义二维求值器

glEnable(GL_MAP2_VERTEX_3);//启用二维求值器

…….

glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0); //计算曲面坐标

}

void myReshape(GLsizei w, GLsizei h)

{

glViewport(0, 0, w, h);// 裁剪坐标映射到窗口平面

glMatrixMode(GL_PROJECTION);//定义 PROJECTION变换

.......

if(w

glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w,4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);

else

glOrtho(-4.0*(GLfloat)w/(GLfloat)h,

4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);

glMatrixMode(GL_MODELVIEW);//定义正交投影

……

}

void main(int argc, char **argv)

{……..

init();

/*使用回调函数机制*/

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutMainLoop();

}

有光照,背景为白色的曲面呈现 没有光照,背景为黑色的曲面呈现

图3三维曲面呈现仿真系统展示图

参考文献:

[1] 丁爱玲.计算机图形学[M].西安:西安电子科大出版社,2005.

[2] 白婷,赵军,朱双华,等.基于OpenGL的三维曲面数据场动态显示[J].计算机与信息技术,2007(5):60-62.

[3] 毛伟冬,唐明理.三维游戏设计师宝典―学openGL编3D游戏[M].成都:四川出版集团,2005.

上一篇:应用VBA技术进行AutoCAD二次开发 下一篇:用C#开发计算器的技术分析