2013-01-24 11:00:22
來(lái)源:
OFweek工控網(wǎng) 導(dǎo)讀:visual c++是當(dāng)前最為流行的軟件開(kāi)發(fā)工具之一,它匯集了微軟公司的技術(shù)精華,不僅全面的貫徹了面向?qū)ο蠹夹g(shù),而且在編譯優(yōu)化技術(shù)方面較其它同類產(chǎn)品具有明顯的優(yōu)勢(shì)。 ![]() 1 引言 opengl是在sgi microsoft dec ibm和intel等多家世界著名計(jì)算機(jī)公司的倡導(dǎo)下,基于sgi的gl標(biāo)準(zhǔn),制定的一個(gè)通用共享的開(kāi)放式三維圖形標(biāo)準(zhǔn)。opengl實(shí)際上是一種圖形與硬件的接口。在仿真三維立體建模、虛擬現(xiàn)實(shí)技術(shù)、3d游戲開(kāi)發(fā)等領(lǐng)域,opengl起著重要作用。 visual c++是當(dāng)前最為流行的軟件開(kāi)發(fā)工具之一,它匯集了微軟公司的技術(shù)精華,不僅全面的貫徹了面向?qū)ο蠹夹g(shù),而且在編譯優(yōu)化技術(shù)方面較其它同類產(chǎn)品具有明顯的優(yōu)勢(shì)。它是一個(gè)徹底的程序員級(jí)的開(kāi)發(fā)環(huán)境,“可視化”的設(shè)計(jì)減少了不少編程的工作量。visual c++6.0更加適應(yīng)當(dāng)今計(jì)算機(jī)網(wǎng)絡(luò)化,運(yùn)行速度快,以及加強(qiáng)數(shù)據(jù)傳輸?shù)膬?yōu)勢(shì)。成為軟件開(kāi)發(fā)的首選工具。 當(dāng)前在visual c++6.0中已經(jīng)集成了opengl圖形標(biāo)準(zhǔn),使得opengl在三維圖形設(shè)計(jì)領(lǐng)域得到廣泛應(yīng)用。 2 opengl的實(shí)現(xiàn)原理 (1) opengl的工作結(jié)構(gòu) opengl的指令的解釋模型是客戶/服務(wù)器模型,即客戶(試圖用opengl進(jìn)行繪制工作的應(yīng)用程序)向服務(wù)器(opengl內(nèi)核)發(fā)布命令,這些opengl命令則是由服務(wù)器來(lái)解釋的。在大多數(shù)情況下,客戶和服務(wù)器是運(yùn)行在同一臺(tái)計(jì)算機(jī)的?;诳蛻?服務(wù)器模式,在網(wǎng)絡(luò)環(huán)境中很容易使用opengl,且在不同計(jì)算機(jī)上的多個(gè)客戶可以得到在其他計(jì)算機(jī)上服務(wù)器的服務(wù)。 opengl的庫(kù)函數(shù)被封裝在opengl32.dll動(dòng)態(tài)鏈接庫(kù)中。從客戶應(yīng)用程序發(fā)布的對(duì)opengl函數(shù)的調(diào)用首先被opengl32.dll處理,在傳給服務(wù)器后,被進(jìn)一步處理,然后傳給ddi,最后傳遞給視頻顯示驅(qū)動(dòng)程序。 (2) opengl的圖形操作步驟 運(yùn)用opengl在計(jì)算機(jī)屏幕上繪出三維場(chǎng)景的基本步驟是: ·設(shè)置像素格式 像素格式告訴opengl繪制風(fēng)格、顏色模式、 顏色位數(shù)等重要信息; · 建立模型 根據(jù)基本圖元建立景物的三維模型,并對(duì)模型進(jìn)行數(shù)學(xué)描述; ·舞臺(tái)布置 把景物放置在三維空間的適當(dāng)位置,設(shè)置三維透視視覺(jué)體以觀察場(chǎng)景; · 效果處理 設(shè)置物體的材質(zhì),加入光照及光照條件; · 光柵化 把景物及其顏色信息轉(zhuǎn)化為可在計(jì)算機(jī)屏幕上顯示的像素信息。 (3) opengl的基本程序結(jié)構(gòu) opengl編程類似與c編程,實(shí)際接口就是c,所以很多有關(guān)opengl的書(shū)中的程序都是使用標(biāo)準(zhǔn)c(或是win32 console application)調(diào)用opengl函數(shù)實(shí)現(xiàn)的。 ·例1用標(biāo)準(zhǔn)c編寫(xiě)一個(gè)“繞y軸旋轉(zhuǎn)的線框型茶壺”的例子來(lái)說(shuō)明opengl的基本程序結(jié)構(gòu)。 例1 opengl例程myteapot.c #include #include “gl.h” //基本庫(kù) #include “glu.h” //實(shí)用庫(kù) #include “glaux.h” //輔助庫(kù) #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); //將當(dāng)前顏色緩存清為窗口的顏色 glpushmatrix(); gltranslatef(0.0,0.0,-80); if (symbol) glrotatef(rot,0,1,0); else gltranslatef(0,0,-rot); glcolor3f(0,1,0.5); //設(shè)置顏色 auxwireteapot(20.0); //繪制一個(gè)線框型的茶壺 glpopmatrix(); glflush(); //強(qiáng)制繪圖完成 auxswapbuffers(); //交換兩個(gè)顏色緩沖區(qū)的內(nèi)容 } 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); //定義了一個(gè)四棱臺(tái)視景體 glmatrixmode(gl_modelview); glloadidentity(); } void main(void) { auxinitdisplaymode(aux_double|aux_rgba); // rgba和雙緩沖模式 auxinitposition(0,0,400,360); //指定要建立的窗口在屏幕窗口中的位置和大小 auxinitwindow(“my teapot ”); //顯示窗口標(biāo)題 init(); auxreshapefunc(reshape); auxidlefunc(stepdisplay); auxmainloop(display); } 3 vc++6.0中的opengl編程 (1) 創(chuàng)建一個(gè)名字為nehe新的單文檔工程; (2) 包含頭文件與函數(shù)庫(kù)文件 在cneheview.h文件首部添加頭文件的包含: ·#include “gl.h” //基本庫(kù) · #include “glu.h” //實(shí)用庫(kù) · #include “glaux.h” //輔助庫(kù) 選擇tool|options菜單命令添加頭文件包含語(yǔ)句,選擇菜單命令project|settings添加庫(kù)文件包含; (3) 設(shè)置像素格式 先在cneheview.h中添加保護(hù)成員函數(shù)bsetup pixelformat(), 添加保護(hù)成員函數(shù)init(),聲明兩個(gè)公有成員:cclientdc*m_pdc; crect m_rect;在構(gòu)造函數(shù) cneheview()中對(duì)m_pdc進(jìn)行初始化。編輯bsetuppixelformat()函數(shù); bool cneheview::bsetuppixelformat() {static pixelformatdescriptor pfd= //初始化像素格式 { sizeof(pixelformatdescriptor), // pfd的大小 1, //版本號(hào) pfd_draw_to_window|pfd_support_opengl| pfd_type_rgba, 24, 0,0,0,0,0,0, //24位顏色深度,缺省的顏色位面數(shù) 0,0,0, //沒(méi)有alpha緩沖, 忽略shift位, 沒(méi)有累積緩沖區(qū) 0,0,0,0, //忽略的累積位 32,0,0, //32位深度緩沖區(qū), 沒(méi)有模板緩沖區(qū), 沒(méi)有輔助緩沖區(qū) 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) 創(chuàng)建著色描述表并當(dāng)前化著色描述表 編輯init()函數(shù); (5) 刪除著色描述表 添加wm_destroy消息,生成ondestroy()函數(shù),在oncreate()函數(shù)中調(diào)用init()函數(shù); (6) 增加wm_size消息,生成消息響應(yīng)函數(shù)onsize(),編輯該函數(shù); (7) 選擇函數(shù)precreatewindow(createstruct& cs),編輯該函數(shù); (8) 在ondraw()函數(shù)中完成繪制工作。 4 應(yīng)用實(shí)例 4.1 機(jī)械手臂控制系統(tǒng)的簡(jiǎn)介 在本實(shí)例中,模擬機(jī)械手臂的控制,系統(tǒng)的工作過(guò)程如下: (1) 控制機(jī)械手臂運(yùn)動(dòng)到工件上方,并夾取工件; (2) 然后控制機(jī)械手臂運(yùn)動(dòng)到檢測(cè)裝置(聲腔)處,檢測(cè)完成后,控制下料筒到相應(yīng)位置; (3) 然后讓機(jī)械手臂運(yùn)動(dòng)到下料口上方,放入工件; (4) 機(jī)械手臂復(fù)位,重復(fù)以上操作。 創(chuàng)建一個(gè)基于cformview的單文檔工程,取名為robort arm。在對(duì)話框idd_robortarm_form的上方添加一個(gè)id號(hào)為idc_buttondraw的按鈕,并為其添加消息響應(yīng)函數(shù)onbuttondraw(),在函數(shù)onbuttondraw()中完成繪制工作。在繪制一個(gè)復(fù)雜的實(shí)際系統(tǒng)時(shí),有很多代碼是重復(fù)的。為了減少由于重復(fù)拷貝而造成的應(yīng)用程序冗長(zhǎng)以及對(duì)系統(tǒng)資源的占用,我們?cè)诒境绦蛑胁捎昧藙?dòng)態(tài)鏈接庫(kù)。 動(dòng)態(tài)鏈接庫(kù)dll(dynamic link library)是一種基于windows的程序模塊,它是一個(gè)包含函數(shù)的庫(kù)文件,可以在運(yùn)行時(shí)被裝入和鏈接。動(dòng)態(tài)鏈接庫(kù)dll和其他c++庫(kù)的區(qū)別在于,動(dòng)態(tài)鏈接庫(kù)dll是在運(yùn)行時(shí)和應(yīng)用程序鏈接,而不是在編譯、鏈接的過(guò)程中被調(diào)用。要使用動(dòng)態(tài)鏈接庫(kù)dll,必須將動(dòng)態(tài)鏈接庫(kù)相應(yīng)的dll文件拷貝到一定的目錄下,在本實(shí)例中,將dll文件放到了應(yīng)用程序所在的子目錄下。 一個(gè)應(yīng)用程序鏈接dll的方法有兩種:顯式鏈接和隱式鏈接。顯式鏈接指動(dòng)態(tài)加載或運(yùn)行時(shí)的鏈接;隱式鏈接指靜態(tài)加載或加載時(shí)動(dòng)態(tài)鏈接。在本實(shí)例中,應(yīng)用的是隱式鏈接。例如:在dll代碼中,聲明了圓柱體和立方體的導(dǎo)出函數(shù)分別為: __declspec(dllexport) void drawcylinder (gldouble dtopradius = 1.0, // 頂面半徑 gldouble dbottomradius = 1.0, // 底面半徑 gldouble dlength = 1.0, // 長(zhǎng)度 gldouble dxrotateptratio = 0.5, // x軸旋轉(zhuǎn)比率 int nslice = 20, // 等分?jǐn)?shù) int mask = 0xff, // 面掩碼 glint* ptexptr = 0, // 貼圖指針 int ntype = 2 // 貼圖類型 ); __declspec(dllexport) void drawcube (glfloat cx = 1.0f, // x軸長(zhǎng)度 glfloat cy = 1.0f, // y軸長(zhǎng)度 glfloat cz = 1.0f, // z軸長(zhǎng)度 int mask = 0xff, // 面掩碼 glint* ptexptr = 0, // 貼圖指針 int ntype = 2 // 貼圖類型 ); 系統(tǒng)由基本的圓柱體和立方體構(gòu)成, 部分?jǐn)?shù)據(jù)結(jié)構(gòu)如下: //定義水平平臺(tái)的長(zhǎng)、寬、高 #define lengthlevel 1.7f #define widthlevel 0.9f #define heightlevel 0.015f //定義傾斜平臺(tái)支柱的長(zhǎng)、寬、高 #define lengthbrace 0.04f #define widthbrace 0.04f #define heightbrace 0.4f //定義放料箱的長(zhǎng)、寬、高 #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 //圓柱體:機(jī)械手的底座和支柱、工件、物料輪、聲腔、下料口、下料筒 void drawrobotsystem:: drawcylinder (gldouble dtopradius, gldouble dbottomradius, gldouble dlength, gldouble dxrotateptratio, int nslice, int mask, glint* ptexptr, int ntype); //立方體:水平平臺(tái)、傾斜平臺(tái)、機(jī)械手的臂和手、表盤(pán)、放料箱 void drawrobotsystem:: drawcube (glfloat cx, glfloat cy, glfloat cz, int mask, glint* ptexptr, int ntype) ; 附圖為完整的模擬系統(tǒng)界面。 4.2 應(yīng)用結(jié)果分析 該仿真系統(tǒng)以三維動(dòng)畫(huà)的方式很好地仿真了機(jī)械手臂控制系統(tǒng)的整個(gè)過(guò)程。其中的動(dòng)畫(huà)包括:物料輪和下料筒的轉(zhuǎn)動(dòng),聲腔的閃爍,機(jī)械手臂的運(yùn)動(dòng)。其中機(jī)械手臂的運(yùn)動(dòng)又包括:機(jī)械手臂的上移、下移、旋轉(zhuǎn)、夾取工件、釋放工件。在實(shí)現(xiàn)動(dòng)畫(huà)時(shí),我們采用的是雙緩存法。它是一種邊畫(huà)邊顯示的實(shí)時(shí)動(dòng)畫(huà)技術(shù)。其基本思想是提供兩個(gè)基本緩沖區(qū),在顯示前臺(tái)緩存內(nèi)容中的一幀畫(huà)面時(shí),后臺(tái)緩存正在繪制下一幀畫(huà)面,當(dāng)繪制完畢,則后臺(tái)緩存內(nèi)容在屏幕上顯示出來(lái)。而前臺(tái)繪制下一副畫(huà)面內(nèi)容。這種方法受圖形生成速度的制約,圖形繪制越復(fù)雜,則速度越慢。由于該系統(tǒng)比較復(fù)雜且要求實(shí)時(shí)性較高,而opengl占用計(jì)算機(jī)的資源又比較大,所以不能做到對(duì)該系統(tǒng)的實(shí)時(shí)仿真。但對(duì)于機(jī)械手臂控制系統(tǒng)的整個(gè)工作過(guò)程還是模擬地很到位的。 5 結(jié)束語(yǔ) 本文提出了利用vc++6.0和opengl對(duì)實(shí)際系統(tǒng)進(jìn)行仿真的方法。并給出了一個(gè)機(jī)械手臂控制系統(tǒng)的模擬實(shí)例,該實(shí)例現(xiàn)已應(yīng)用于濰坊市怡力達(dá)電聲有限公司的“ecm自動(dòng)測(cè)試視覺(jué)識(shí)別與控制系統(tǒng)”,目前該系統(tǒng)運(yùn)行良好。 |
|
來(lái)自: 牛人的尾巴 > 《機(jī)器人設(shè)計(jì)》