2013-01-24 11:00:22
来源:
OFweek工控网 导读:visual c++是当前最为流行的软件开发工具之一,它汇集了微软公司的技术精华,不仅全面的贯彻了面向对象技术,而且在编译优化技术方面较其它同类产品具有明显的优势。 ![]() 1 引言 opengl是在sgi microsoft dec ibm和intel等多家世界著名计算机公司的倡导下,基于sgi的gl标准,制定的一个通用共享的开放式三维图形标准。opengl实际上是一种图形与硬件的接口。在仿真三维立体建模、虚拟现实技术、3d游戏开发等领域,opengl起着重要作用。 visual c++是当前最为流行的软件开发工具之一,它汇集了微软公司的技术精华,不仅全面的贯彻了面向对象技术,而且在编译优化技术方面较其它同类产品具有明显的优势。它是一个彻底的程序员级的开发环境,“可视化”的设计减少了不少编程的工作量。visual c++6.0更加适应当今计算机网络化,运行速度快,以及加强数据传输的优势。成为软件开发的首选工具。 当前在visual c++6.0中已经集成了opengl图形标准,使得opengl在三维图形设计领域得到广泛应用。 2 opengl的实现原理 (1) opengl的工作结构 opengl的指令的解释模型是客户/服务器模型,即客户(试图用opengl进行绘制工作的应用程序)向服务器(opengl内核)发布命令,这些opengl命令则是由服务器来解释的。在大多数情况下,客户和服务器是运行在同一台计算机的。基于客户/服务器模式,在网络环境中很容易使用opengl,且在不同计算机上的多个客户可以得到在其他计算机上服务器的服务。 opengl的库函数被封装在opengl32.dll动态链接库中。从客户应用程序发布的对opengl函数的调用首先被opengl32.dll处理,在传给服务器后,被进一步处理,然后传给ddi,最后传递给视频显示驱动程序。 (2) opengl的图形操作步骤 运用opengl在计算机屏幕上绘出三维场景的基本步骤是: ·设置像素格式 像素格式告诉opengl绘制风格、颜色模式、 颜色位数等重要信息; · 建立模型 根据基本图元建立景物的三维模型,并对模型进行数学描述; ·舞台布置 把景物放置在三维空间的适当位置,设置三维透视视觉体以观察场景; · 效果处理 设置物体的材质,加入光照及光照条件; · 光栅化 把景物及其颜色信息转化为可在计算机屏幕上显示的像素信息。 (3) opengl的基本程序结构 opengl编程类似与c编程,实际接口就是c,所以很多有关opengl的书中的程序都是使用标准c(或是win32 console application)调用opengl函数实现的。 ·例1用标准c编写一个“绕y轴旋转的线框型茶壶”的例子来说明opengl的基本程序结构。 例1 opengl例程myteapot.c #include #include “gl.h” //基本库 #include “glu.h” //实用库 #include “glaux.h” //辅助库 #include void init (void);void callback reshape (glsizei w,glsizei h); void callback display (void);void callback stepdisplay (void); int symbol=1; float rot=0; void init (void) { glclearcolor(0.0,0.0,0.0,0.0); //将窗口清为黑色 } void callback stepdisplay (void) { rot+=4; if(rot》360) rot=0; display (); } void callback display (void) { glclear (gl_color_buffer_bit); //将当前颜色缓存清为窗口的颜色 glpushmatrix(); gltranslatef(0.0,0.0,-80); if (symbol) glrotatef(rot,0,1,0); else gltranslatef(0,0,-rot); glcolor3f(0,1,0.5); //设置颜色 auxwireteapot(20.0); //绘制一个线框型的茶壶 glpopmatrix(); glflush(); //强制绘图完成 auxswapbuffers(); //交换两个颜色缓冲区的内容 } void callback reshape (glsizei w,glsizei h) { if(h= =0) h=1; glviewport(0,0,w,h) //定义视口; glmatrixmode(gl_projection); //定义操作矩阵的类型为投影操作矩阵 glloadidentity(); gluperspective(90,w/h,1.0,200); //定义了一个四棱台视景体 glmatrixmode(gl_modelview); glloadidentity(); } void main(void) { auxinitdisplaymode(aux_double|aux_rgba); // rgba和双缓冲模式 auxinitposition(0,0,400,360); //指定要建立的窗口在屏幕窗口中的位置和大小 auxinitwindow(“my teapot ”); //显示窗口标题 init(); auxreshapefunc(reshape); auxidlefunc(stepdisplay); auxmainloop(display); } 3 vc++6.0中的opengl编程 (1) 创建一个名字为nehe新的单文档工程; (2) 包含头文件与函数库文件 在cneheview.h文件首部添加头文件的包含: ·#include “gl.h” //基本库 · #include “glu.h” //实用库 · #include “glaux.h” //辅助库 选择tool|options菜单命令添加头文件包含语句,选择菜单命令project|settings添加库文件包含; (3) 设置像素格式 先在cneheview.h中添加保护成员函数bsetup pixelformat(), 添加保护成员函数init(),声明两个公有成员:cclientdc*m_pdc; crect m_rect;在构造函数 cneheview()中对m_pdc进行初始化。编辑bsetuppixelformat()函数; bool cneheview::bsetuppixelformat() {static pixelformatdescriptor pfd= //初始化像素格式 { sizeof(pixelformatdescriptor), // pfd的大小 1, //版本号 pfd_draw_to_window|pfd_support_opengl| pfd_type_rgba, 24, 0,0,0,0,0,0, //24位颜色深度,缺省的颜色位面数 0,0,0, //没有alpha缓冲, 忽略shift位, 没有累积缓冲区 0,0,0,0, //忽略的累积位 32,0,0, //32位深度缓冲区, 没有模板缓冲区, 没有辅助缓冲区 pfd_main_plane, //主要层次方式 0, 0,0,0 //保留位,屏蔽层次掩模 }; int pixelformat; if ((pixelformat=choosepixelformat(m_pdc-》getsafehdc(),&pfd))==0) {messagebox(“choosepixelformat failed”); return false; } if (setpixelformat(m_pdc-》getsafehdc(),pixelformat,&pfd)==false) {messagebox(“setpixelformat failed”); return false; } return true; } (4) 创建着色描述表并当前化着色描述表 编辑init()函数; (5) 删除着色描述表 添加wm_destroy消息,生成ondestroy()函数,在oncreate()函数中调用init()函数; (6) 增加wm_size消息,生成消息响应函数onsize(),编辑该函数; (7) 选择函数precreatewindow(createstruct& cs),编辑该函数; (8) 在ondraw()函数中完成绘制工作。 4 应用实例 4.1 机械手臂控制系统的简介 在本实例中,模拟机械手臂的控制,系统的工作过程如下: (1) 控制机械手臂运动到工件上方,并夹取工件; (2) 然后控制机械手臂运动到检测装置(声腔)处,检测完成后,控制下料筒到相应位置; (3) 然后让机械手臂运动到下料口上方,放入工件; (4) 机械手臂复位,重复以上操作。 创建一个基于cformview的单文档工程,取名为robort arm。在对话框idd_robortarm_form的上方添加一个id号为idc_buttondraw的按钮,并为其添加消息响应函数onbuttondraw(),在函数onbuttondraw()中完成绘制工作。在绘制一个复杂的实际系统时,有很多代码是重复的。为了减少由于重复拷贝而造成的应用程序冗长以及对系统资源的占用,我们在本程序中采用了动态链接库。 动态链接库dll(dynamic link library)是一种基于windows的程序模块,它是一个包含函数的库文件,可以在运行时被装入和链接。动态链接库dll和其他c++库的区别在于,动态链接库dll是在运行时和应用程序链接,而不是在编译、链接的过程中被调用。要使用动态链接库dll,必须将动态链接库相应的dll文件拷贝到一定的目录下,在本实例中,将dll文件放到了应用程序所在的子目录下。 一个应用程序链接dll的方法有两种:显式链接和隐式链接。显式链接指动态加载或运行时的链接;隐式链接指静态加载或加载时动态链接。在本实例中,应用的是隐式链接。例如:在dll代码中,声明了圆柱体和立方体的导出函数分别为: __declspec(dllexport) void drawcylinder (gldouble dtopradius = 1.0, // 顶面半径 gldouble dbottomradius = 1.0, // 底面半径 gldouble dlength = 1.0, // 长度 gldouble dxrotateptratio = 0.5, // x轴旋转比率 int nslice = 20, // 等分数 int mask = 0xff, // 面掩码 glint* ptexptr = 0, // 贴图指针 int ntype = 2 // 贴图类型 ); __declspec(dllexport) void drawcube (glfloat cx = 1.0f, // x轴长度 glfloat cy = 1.0f, // y轴长度 glfloat cz = 1.0f, // z轴长度 int mask = 0xff, // 面掩码 glint* ptexptr = 0, // 贴图指针 int ntype = 2 // 贴图类型 ); 系统由基本的圆柱体和立方体构成, 部分数据结构如下: //定义水平平台的长、宽、高 #define lengthlevel 1.7f #define widthlevel 0.9f #define heightlevel 0.015f //定义倾斜平台支柱的长、宽、高 #define lengthbrace 0.04f #define widthbrace 0.04f #define heightbrace 0.4f //定义放料箱的长、宽、高 #define lengthbox 0.05f #define widthbox 0.06f #define heightbox 0.05f //定义物料轮的半径和高度 #define radiusdisk 0.14f #define heightdisk 0.02f //定义工件的半径和高度 #define radiusworkpiece 0.025f #define heightworkpiece 0.03f //圆柱体:机械手的底座和支柱、工件、物料轮、声腔、下料口、下料筒 void drawrobotsystem:: drawcylinder (gldouble dtopradius, gldouble dbottomradius, gldouble dlength, gldouble dxrotateptratio, int nslice, int mask, glint* ptexptr, int ntype); //立方体:水平平台、倾斜平台、机械手的臂和手、表盘、放料箱 void drawrobotsystem:: drawcube (glfloat cx, glfloat cy, glfloat cz, int mask, glint* ptexptr, int ntype) ; 附图为完整的模拟系统界面。 4.2 应用结果分析 该仿真系统以三维动画的方式很好地仿真了机械手臂控制系统的整个过程。其中的动画包括:物料轮和下料筒的转动,声腔的闪烁,机械手臂的运动。其中机械手臂的运动又包括:机械手臂的上移、下移、旋转、夹取工件、释放工件。在实现动画时,我们采用的是双缓存法。它是一种边画边显示的实时动画技术。其基本思想是提供两个基本缓冲区,在显示前台缓存内容中的一帧画面时,后台缓存正在绘制下一帧画面,当绘制完毕,则后台缓存内容在屏幕上显示出来。而前台绘制下一副画面内容。这种方法受图形生成速度的制约,图形绘制越复杂,则速度越慢。由于该系统比较复杂且要求实时性较高,而opengl占用计算机的资源又比较大,所以不能做到对该系统的实时仿真。但对于机械手臂控制系统的整个工作过程还是模拟地很到位的。 5 结束语 本文提出了利用vc++6.0和opengl对实际系统进行仿真的方法。并给出了一个机械手臂控制系统的模拟实例,该实例现已应用于潍坊市怡力达电声有限公司的“ecm自动测试视觉识别与控制系统”,目前该系统运行良好。 |
|