版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
計(jì)算機(jī)圖形學(xué)試驗(yàn)指導(dǎo)書[1]PAGE《計(jì)算機(jī)圖形學(xué)》實(shí)驗(yàn)指導(dǎo)書Ver2.0傅由甲盧宇編重慶理工大學(xué)計(jì)算機(jī)科學(xué)與工程學(xué)院2008年10月PAGE16目錄深度優(yōu)先線框繪圖方式(depth_cued)--用線框方式繪圖,增加模擬人眼看物體一樣的效果,遠(yuǎn)處的物體比近處的物體要暗些;反走樣線框繪圖方式(antialiased)--用線框方式繪圖,繪圖時(shí)采用反走樣技術(shù)以減少圖形線條的參差不齊;平面消隱繪圖方式(flat_shade)--對(duì)模型的隱藏面進(jìn)行消隱,對(duì)模型的平面單元按光照程度進(jìn)行著色但不進(jìn)行光滑處理;光滑消隱繪圖方式(smooth_shade)--對(duì)模型進(jìn)行消隱按光照渲染著色的過程中再進(jìn)行光滑處理,這種方式更接近于現(xiàn)實(shí);加陰影和紋理的繪圖方式(shadows,textures)--在模型表面貼上紋理甚至于加上光照陰影,使得三維景觀象照片一樣;運(yùn)動(dòng)模糊的繪圖方式(motion-blured)--模擬物體運(yùn)動(dòng)時(shí)人眼觀察所感覺的動(dòng)感現(xiàn)象;大氣環(huán)境效果(atmosphere-effects)--在三維景觀中加入如霧等大氣環(huán)境效果,使人身臨其境;深度域效果(depth-of-effects)--類似于照相機(jī)鏡頭效果,模型在聚焦點(diǎn)處清晰,反之則模糊。整個(gè)OpenGL的基本工作流程如下圖幾何頂點(diǎn)數(shù)據(jù)幾何頂點(diǎn)數(shù)據(jù)顯示列表評(píng)價(jià)器逐個(gè)頂點(diǎn)操作和圖元組裝紋理映射光柵化片元操作幀緩沖區(qū)像素?cái)?shù)據(jù)像素操作圖1-1OpenGL基本工作流程其中幾何頂點(diǎn)數(shù)據(jù)包括模型的頂點(diǎn)集、線集、多邊形集,這些數(shù)據(jù)經(jīng)過流程圖的上部,包括運(yùn)算器、逐個(gè)頂點(diǎn)操作等;像素?cái)?shù)據(jù)包括像素集、影像集、位圖集等,像素?cái)?shù)據(jù)的處理方式與幾何頂點(diǎn)數(shù)據(jù)的處理方式是不同的,但它們都經(jīng)過光柵化、逐個(gè)片元(Fragment)處理直至把最后的光柵數(shù)據(jù)寫入幀緩沖器。在OpenGL中的所有數(shù)據(jù)包括幾何頂點(diǎn)數(shù)據(jù)和像素?cái)?shù)據(jù)都可以被存儲(chǔ)在顯示列表中或者立即可以得到處理。OpenGL要求把所有的幾何圖形單元都用頂點(diǎn)來描述,這樣運(yùn)算器和逐個(gè)頂點(diǎn)計(jì)算操作都可以針對(duì)每個(gè)頂點(diǎn)進(jìn)行計(jì)算和操作,然后進(jìn)行光柵化形成圖形片元;對(duì)于像素?cái)?shù)據(jù),像素操作結(jié)果被存儲(chǔ)在紋理組裝用的內(nèi)存中,再象幾何頂點(diǎn)操作一樣光柵化形成圖形片元。整個(gè)流程操作的最后,圖形片元都要進(jìn)行一系列的逐個(gè)片元操作,這樣最后的像素值被送入幀緩沖器實(shí)現(xiàn)圖形的顯示。在OpenGL中進(jìn)行主要的圖形操作直至在計(jì)算機(jī)屏幕上渲染繪制出三維圖形景觀的基本步驟為:根據(jù)基本圖形單元建立景物模型,并且對(duì)所建立的模型進(jìn)行數(shù)學(xué)描述(OpenGL中把點(diǎn)、線、多邊形、圖像和位圖都作為基本圖形單元);把景物模型放在三維空間中的合適的位置,并且設(shè)置視點(diǎn)(viewpoint)以觀察所感興趣的景觀;計(jì)算模型中所有物體的色彩,其中的色彩根據(jù)應(yīng)用要求來確定,同時(shí)確定光照條件、紋理粘貼方式等;把景物模型的數(shù)學(xué)描述及其色彩信息轉(zhuǎn)換至計(jì)算機(jī)屏幕上的像素,這個(gè)過程也就是光柵化(rasterization)。在這些步驟的執(zhí)行過程中,OpenGL可能執(zhí)行其他的一些操作,例如自動(dòng)消隱處理等。另外,景物光柵化之后被送入幀緩沖器之前還可以根據(jù)需要對(duì)像素?cái)?shù)據(jù)進(jìn)行操作。OpenGL能夠?qū)φ麄€(gè)三維模型進(jìn)行渲染著色,從而繪制出與客觀世界十分類似的三維景象。另外OpenGL還可以進(jìn)行三維交互、動(dòng)作模擬等。具體的功能主要有以下這些內(nèi)容。(1)模型繪制OpenGL能夠繪制點(diǎn)、線和多邊形。應(yīng)用這些基本的形體,可以構(gòu)造出幾乎所有的三維模型。OpenGL通常用模型的多邊形的頂點(diǎn)來描述三維模型。(2)模型觀察在建立了三維景物模型后,就需要用OpenGL描述如何觀察所建立的三維模型。觀察三維模型是通過一系列的坐標(biāo)變換進(jìn)行的。模型的坐標(biāo)變換使觀察者能夠在視點(diǎn)位置觀察與視點(diǎn)相適應(yīng)的三維模型景觀。在整個(gè)三維模型的觀察過程中,投影變換的類型決定觀察三維模型的觀察方式,不同的投影變換得到的三維模型的景象也是不同的。最后的視窗變換則對(duì)模型的景象進(jìn)行裁剪縮放,即決定整個(gè)三維模型在屏幕上的圖像。(3)顏色模式的指定OpenGL應(yīng)用了一些專門的函數(shù)來指定三維模型的顏色。程序開發(fā)者可以選擇二個(gè)顏色模式,即RGBA模式和顏色表模式。在RGBA模式中,顏色直接由RGB值來指定;在顏色表模式中,顏色值則由顏色表中的一個(gè)顏色索引值來指定。開發(fā)者還可以選擇平面著色和光滑著色二種著色方式對(duì)整個(gè)三維景觀進(jìn)行著色。(4)光照應(yīng)用用OpenGL繪制的三維模型必須加上光照才能更加與客觀物體相似。OpenGL提供了管理四種光(自發(fā)光、環(huán)境光、鏡面光和漫反射光)的方法,另外還可以指定模型表面的反射特性。(5)圖像效果增強(qiáng)OpenGL提供了一系列的增強(qiáng)三維景觀的圖像效果的函數(shù),這些函數(shù)通過反走樣、混合和霧化來增強(qiáng)圖像的效果。反走樣用于改善圖像中線段圖形的鋸齒而更平滑,混合用于處理模型的半透明效果,霧使得影像從視點(diǎn)到遠(yuǎn)處逐漸褪色,更接近于真實(shí)。(6)位圖和圖像處理OpenGL還提供了專門對(duì)位圖和圖像進(jìn)行操作的函數(shù)。(7)紋理映射三維景物因缺少景物的具體細(xì)節(jié)而顯得不夠真實(shí),為了更加逼真地表現(xiàn)三維景物,OpenGL提供了紋理映射的功能。OpenGL提供的一系列紋理映射函數(shù)使得開發(fā)者可以十分方便地把真實(shí)圖像貼到景物的多邊形上,從而可以在視窗內(nèi)繪制逼真的三維景觀。(8)實(shí)時(shí)動(dòng)畫為了獲得平滑的動(dòng)畫效果,需要先在內(nèi)存中生成下一幅圖像,然后把已經(jīng)生成的圖像從內(nèi)存拷貝到屏幕上,這就是OpenGL的雙存技術(shù)(doublebuffer)。OpenGL提供了雙緩存技術(shù)的一系列函數(shù)。(9)交互技術(shù)目前有許多圖形應(yīng)用需要人機(jī)交互,OpenGL提供了方便的三維圖形人機(jī)交互接口,用戶可以選擇修改三維景觀中的物體。1.2OpenGL函數(shù)的語法OpenGL函數(shù)以“gl”為前綴,并把組成函數(shù)名的每個(gè)單詞的首字母進(jìn)行大寫(glClearColor())。類似地,OpenGL還定義了以前綴GL_開頭的常量,所有單詞使用大寫形式,并以下劃線分割(例如GL_COLOR_BUFFER_BIT)。此外,有些函數(shù),同一函數(shù)有多個(gè)不同版本,如glColor3f(),glColor3ub(),glColor3bv()等都用于設(shè)置當(dāng)前繪圖顏色,其中“3”表示函數(shù)接受3個(gè)參數(shù),“f”表示參數(shù)類型為浮點(diǎn)數(shù),“ub”表示參數(shù)類型為8位無符號(hào)整數(shù),“bv”表1-1列出用于指定數(shù)據(jù)類型的后綴字母,以供參考:后綴數(shù)據(jù)類型對(duì)應(yīng)典型C語言O(shè)penGL類型定義b8位整數(shù)signedcharGLbytes16位整數(shù)shortGLshorti32位整數(shù)int或longGLint,GLsizeif32位浮點(diǎn)數(shù)floatGLfloat,GLclampfd64位浮點(diǎn)數(shù)doubleGLdouble,GLclampdub8位無符號(hào)整數(shù)unsignedcharGLubyte,GLbooleanus16位無符號(hào)整數(shù)unsignedshortGLushortui32位無符號(hào)整數(shù)unsignedint或unsignedlongGLuint,GLenum,GLbitfield1.3OpenGL是狀態(tài)機(jī)OpenGL是個(gè)狀態(tài)機(jī)。設(shè)置它的各種狀態(tài)(或模式),則這些狀態(tài)一直生效,直到它們被修改。OpenGL所維護(hù)的狀態(tài)變量很多,例如顏色,控制當(dāng)前視圖和投影變換,直線和多邊形點(diǎn)畫模式,多邊形繪圖模式,像素包裝約定,光照位置和特征,被繪制物體的材料屬性等。許多表示模式的狀態(tài)變量可以用glEnable()和glDisable()函數(shù)進(jìn)行啟用和禁用。每個(gè)狀態(tài)變量(或模式)都有一個(gè)默認(rèn)值。任何時(shí)候,都可以向系統(tǒng)查詢每個(gè)狀態(tài)變量的當(dāng)前值。使用6個(gè)函數(shù)之一完成這個(gè)任務(wù):glGetBooleanv(),glGetDoublev(),glGetFloatv(),glGetIntegerv(),glGetPointerv(),glIsEnabled()。所選擇的具體函數(shù)取決于希望返回的結(jié)果的數(shù)據(jù)類型。有些狀態(tài)變量還有更為特定的查詢函數(shù),可以查閱《OpenGL編程指南》等參考書,在此不在詳述。1.4OpenGL相關(guān)的函數(shù)庫OpenGL提供了一組功能強(qiáng)大但又比較原始的渲染函數(shù),所有高層繪圖操作必須根據(jù)這些函數(shù)完成。同樣,OpenGL程序必須使用窗口系統(tǒng)的底層機(jī)制。有一些函數(shù)庫可以用來幫助簡(jiǎn)化任務(wù),它們是:OpenGL工具函數(shù)庫(GLU)包含了一些函數(shù),它們利用低層OpenGL函數(shù)來執(zhí)行諸如為特定視圖定向和投影設(shè)置矩陣、多邊形分格化以及表面渲染等任務(wù)。所有OpenGL實(shí)現(xiàn)都把這個(gè)函數(shù)庫作為它的一部分。GLU函數(shù)都使用前綴glu。所有的窗口系統(tǒng)都提供一個(gè)函數(shù)庫,對(duì)該窗口系統(tǒng)的功能進(jìn)行擴(kuò)展,以支持OpenGL渲染。對(duì)于MicrosoftWindows,WGL函數(shù)提供了Windows到OpenGL的接口。所有的WGL函數(shù)都使用前綴wgl。OpenGL實(shí)用工具包(GLUT)是MarkKilgard所編寫的一個(gè)獨(dú)立于窗口系統(tǒng)的工具包,其目的是隱藏不同窗口系統(tǒng)API的復(fù)雜性。GLUT函數(shù)使用前綴glut。1.5OpenGL的緩沖區(qū)OpenGL需要用到4個(gè)緩沖區(qū)進(jìn)行圖形顯示,它們分別是:顏色緩存、深度緩存、模板緩存和累積緩存。這里我們只介紹顏色緩存和深度緩存的基本概念,更多內(nèi)容請(qǐng)參閱《OpenGL編程指南》。1.5.1顏色緩存顏色緩存由紅、綠、藍(lán)、alpha位等位平面(bitplane)組成的,有前緩存(frontbuffer)、后緩存(backbuffer)、左前(front_left)和右前(front_right)緩存、左后(back_left)和右后(back_right)緩存。左前緩存是必須的顏色緩存。前緩存是可見緩存,后緩存是不可見緩存。前后緩存技術(shù)可以實(shí)現(xiàn)動(dòng)畫操作。與顏色緩存相關(guān)的主要函數(shù)有:清除顏色緩存:glClear(GL_COLOR_BUFFER_BIT),用于清除當(dāng)前顯示緩沖區(qū)內(nèi)容,為開始新的繪制做好準(zhǔn)備。設(shè)置清除顏色:glClearColor(red,green,blue,alpha),用當(dāng)前顏色(red,green,blue,alpha)清除當(dāng)前顯示緩沖區(qū)內(nèi)容,為開始新的繪制做好準(zhǔn)備。屏蔽顏色緩存:glColorMask(),分別設(shè)置紅、綠、藍(lán)和alpha的可寫屬性。選擇顏色緩存:glDrawBuffer(),對(duì)雙緩存中的一個(gè)進(jìn)行選擇。交換顏色緩存:swapBuffer(),交換前后緩存中的顏色,以實(shí)現(xiàn)動(dòng)畫。1.5.2深度緩存深度緩存也叫Z-buffer,它記錄每個(gè)像素點(diǎn)所對(duì)應(yīng)的物體點(diǎn)到視點(diǎn)的距離,由此決定表面的可見性。在進(jìn)行消隱的時(shí)候,OpenGL必須知道各物體間的相對(duì)位置關(guān)系,從而模擬出物體相互遮擋的效果,因此,需要進(jìn)行深度測(cè)試。而深度測(cè)試的結(jié)果就生成了深度緩存。與深度緩存相關(guān)的OpenGL操作主要有:清除深度緩存:glClear(GL_DEPTH_BUFFER_BIT),用于清除當(dāng)前顯示緩沖區(qū)內(nèi)容,為開始新的繪制做好準(zhǔn)備。設(shè)置清除值:glClearDepth(1.0),1.0為最大深度。屏蔽深度緩存:glDepthMask(GL_TRUE),表示可以寫深度緩存;glDepthMask(GL_FALSE),表示禁止寫深度緩存。啟動(dòng)和關(guān)閉深度測(cè)試:glEnableGL_DEPTH_TEST),表示開啟深度測(cè)試;glDisable(GL_DEPTH_TEST),表示禁止深度測(cè)試。確定測(cè)試條件:glDepthFunc(),根據(jù)函數(shù)參數(shù)確定測(cè)試方式,具體的參數(shù)說明請(qǐng)參考實(shí)驗(yàn)五。確定深度范圍:glDepthRange(GLclampdzNear,GLclampdzFar),參數(shù)zNear和zFar分別說明視景體的前景和后景面向窗口坐標(biāo)映射的規(guī)格化坐標(biāo),便于后續(xù)使用。2MicrosoftVisualC++6.0MFC編程基礎(chǔ)2.1MFC事件驅(qū)動(dòng)簡(jiǎn)介用OpenGL編寫的程序結(jié)構(gòu)類似于用其他語言編寫的程序。實(shí)際上,OpenGL是一個(gè)豐富的三維圖形函數(shù)庫,編寫OpenGL程序并非難事,只需在基本C語言中調(diào)用這些函數(shù),用法同TurboC、VC++等類似。微軟基礎(chǔ)類庫(Microsoftfoundationclass,MFC)是微軟為Windows程序員提供的一個(gè)面向?qū)ο蟮腤indows編程接口,它大大簡(jiǎn)化了Windows編程工作,使開發(fā)人員不必從頭設(shè)計(jì)創(chuàng)建和管理一個(gè)標(biāo)準(zhǔn)Windows應(yīng)用程序所需的程序,節(jié)省了時(shí)間;同時(shí)它提供了大量代碼,指導(dǎo)用戶編程時(shí)實(shí)現(xiàn)某些技術(shù)和功能。在事件驅(qū)動(dòng)編程方面,通過MFC的核心——消息映射機(jī)制,定義一個(gè)消息與處理函數(shù)的對(duì)照表,實(shí)現(xiàn)消息處理的分離編程。每當(dāng)產(chǎn)生一個(gè)事件,便可通過這個(gè)對(duì)照表找到相應(yīng)的消息處理函數(shù),執(zhí)行這個(gè)函數(shù)完成相應(yīng)功能;相應(yīng)的,程序員只需利用VC集成開發(fā)環(huán)境提供的工具指定當(dāng)鼠標(biāo)在哪個(gè)GUI對(duì)象上操作時(shí)執(zhí)行哪個(gè)函數(shù)即可,MFC事件驅(qū)動(dòng)編程模式如圖2.1所示。2.1MFC中事件驅(qū)動(dòng)編程模式為了提高交互式繪圖性能,為以后二維/三維開發(fā)打下基礎(chǔ),考慮到MicrosoftVisualC++的MFC開發(fā)環(huán)境提供了GDI工具及相對(duì)較好的交互式繪圖環(huán)境,所以,本書采用該環(huán)境進(jìn)行二維/三維圖形的實(shí)驗(yàn)。2.2MFC事件驅(qū)動(dòng)編程2.2.1建立MFC工程步驟一:打開MicrosoftVisualC++6.0應(yīng)用程序。在菜單中選擇“文件”—>“新建”打開建立用戶應(yīng)用程序?qū)υ捒?,在?duì)話框的“工程”頁面左邊選擇MFCAppWizard[exe];在右邊“位置”編輯框中鍵入要建的項(xiàng)目存放位置,例如D盤根目錄;在右邊“工程”編輯框中鍵入要建的項(xiàng)目的名稱,例如MFCTest,這時(shí)我們會(huì)看到“位置”編輯框中信息變?yōu)椤癉:\MFCTest”,表示我們的項(xiàng)目文件都將存放在這個(gè)目錄中。如圖2.2所示。圖2.2:建立MFC應(yīng)用程序步驟二:我們點(diǎn)擊“確定”按鈕進(jìn)行下一步設(shè)置。在“MFCAppWizard–Step1”對(duì)話框中有“S單個(gè)文檔”、“M多個(gè)文檔”“D基本對(duì)話框”三個(gè)選項(xiàng)。“S單個(gè)文檔”表示用戶程序一次只能打開一個(gè)文檔窗口;“M多個(gè)文檔”表示用戶程序除了一個(gè)文檔主窗口外,還可以打開若干個(gè)顯示不同文檔的小窗口,即子窗口;“D基本對(duì)話框”表示用戶程序的界面是對(duì)話框形式的。這里我們選擇“S單個(gè)文檔”,然后,單擊“下一個(gè)”按鈕。如圖2圖2.3:MFCAppWizard–Step1步驟三:“MFCAppWizard–Step2of6”對(duì)話框是關(guān)于所建立的程序是否用到數(shù)據(jù)庫,我們選擇“否”,然后,單擊“下一個(gè)”步驟四:“MFCAppWizard–Step3of6”對(duì)話框是關(guān)于所建立的程序是否用到復(fù)合文檔,我們選擇“否”,然后,單擊“下一個(gè)”步驟五:“MFCAppWizard–Step4of6”對(duì)話框是關(guān)于所建立的程序的特點(diǎn)及是否支持打印及預(yù)覽,我們選擇其默認(rèn)設(shè)置,單擊“下一個(gè)”步驟六:“MFCAppWizard–Step5of6”對(duì)話框是關(guān)于所建立的程序的風(fēng)格等的設(shè)置,我們選擇其默認(rèn)設(shè)置,單擊“下一步”步驟七:“MFCAppWizard–Step6of6”對(duì)話框我們看到VC開發(fā)環(huán)境已經(jīng)為我們的用戶程序生成了四個(gè)類,包括它們的類名、頭文件(.h)、實(shí)現(xiàn)文件(.cpp)及基類。單擊“完成”圖2.4:MFCAppWizard–Step6of6完成了MFC應(yīng)用程序框架后我們看到MFC用戶程序開發(fā)環(huán)境,如圖2.5所示。圖2.5:MFC用戶程序開發(fā)環(huán)境開發(fā)環(huán)境的左邊是項(xiàng)目工作區(qū),有三頁,依次為類視圖(ClassView)、資源視圖(ResourceView)及文件視圖(FileView),分別對(duì)應(yīng)生成的類、項(xiàng)目資源及相應(yīng)文件。開發(fā)環(huán)境右邊文檔區(qū)中則顯示相應(yīng)類的具體代碼。2.2.2編譯和運(yùn)行MFC用戶程序項(xiàng)目現(xiàn)在開發(fā)環(huán)境已為我們搭建好了框架,我們只需對(duì)其進(jìn)行編譯和連接就可以得到一個(gè)用戶程序的框架。步驟一:在前面打開MFCTest項(xiàng)目中,選擇菜單的“編譯”(Build)—>“全部重建”(RebuildAll),對(duì)剛才生成的應(yīng)用程序框架進(jìn)行編譯和連接。成功后在開發(fā)環(huán)境的輸出欄里看到“MFCTest.exe-0error(s),0warning(s)”提示。步驟二:選擇菜單的“編譯”—>“執(zhí)行MFCTest.exe”,可看到生成的MFC應(yīng)用程序框架。如圖2.6所示。圖2.6:MFCTest應(yīng)用程序框架2.2.3關(guān)閉和打開用戶程序項(xiàng)目要關(guān)閉MFCTest項(xiàng)目,只需選擇菜單的“文件”—>“關(guān)閉工作區(qū)”(CloseWorkspace);反之,要打開一個(gè)已存在的用戶程序項(xiàng)目選擇菜單項(xiàng)“文件”—>“打開工作區(qū)”(OpenWorkspace),在彈出的文件對(duì)話框中找到要打開的項(xiàng)目名稱,這里是D:\MFCTest\MFCTest.dsw。如圖2.7所示。圖2.7:打開MFCTest項(xiàng)目2.2.4在MFC中建立新類的方法右鍵單擊項(xiàng)目工作區(qū)的類視圖頁面的項(xiàng)目名稱,在右鍵菜單中選擇“NewClass…”,彈出如圖2.8所示“新類(NewClass)”對(duì)話框:圖2.8建立新類在Classtype中選擇新建類的類型,其中“GenericClass”表示新建一般類,這也是本書實(shí)驗(yàn)中建類時(shí)經(jīng)常用到的選項(xiàng)。在Name欄中鍵入類名,按照VC約定,新類以”C”作為前綴,表示建立的是一個(gè)類,VC將新建的類按頭文件(*.h)和實(shí)現(xiàn)文件(*.cpp)分開保存,并以去掉“C”前綴的類名作為文件名。如果建立的類是一個(gè)派生類,則在“Bassclass”欄中選擇基類。最后點(diǎn)“OK”鍵完成類的建立。2.2.5在MFC中添加類成員變量和成員函數(shù)的方法右鍵單擊項(xiàng)目工作區(qū)的類視圖頁面中需添加成員的類名,在右鍵菜單中選擇“AddMemberFunction…”,添加成員函數(shù),或者“AddMemberVariable…”添加成員變量,根據(jù)約定,類的成員變量名一律以”m_”為前綴,以便和臨時(shí)變量或全局變量區(qū)別。2.2.6在MFC中添加菜單項(xiàng)方法步驟一:切換到項(xiàng)目左邊工作區(qū)的資源視圖頁(ResourceView),雙擊“Menu”文件夾下的IDR_MAINFRAME,則項(xiàng)目右邊出現(xiàn)菜單欄。如圖2.9所示。預(yù)留菜項(xiàng)單菜單欄預(yù)留菜項(xiàng)單菜單欄圖2.9菜單編輯界面步驟二:雙擊菜單欄上的預(yù)留菜單項(xiàng),彈出菜單項(xiàng)屬性對(duì)話框。在其標(biāo)題欄中輸入菜單項(xiàng)標(biāo)題,如“茶壺”,在ID欄中給菜單項(xiàng)取一個(gè)ID號(hào),如圖2.10所示。如果沒有取,系統(tǒng)自動(dòng)命名該菜單項(xiàng)ID,如果對(duì)自動(dòng)命名的ID不滿意(大多數(shù)情況),可以再次打開屬性對(duì)話框,給菜單項(xiàng)取一個(gè)自己滿意的ID。2.10菜單項(xiàng)屬性對(duì)話框2.2.7在MFC中添加消息響應(yīng)的方法按照MFC規(guī)定,對(duì)于窗口類,如視圖類,對(duì)話框類等可以添加事件響應(yīng)處理函數(shù)。方法如下:切換到項(xiàng)目左邊工作區(qū)的類視圖頁(ClassView),鼠標(biāo)右擊需添加事件響應(yīng)的窗口類,在彈出的下拉列表中選擇“AddWindowsMessageHandler…”,彈出“NewWindowsMessageandEventHandlersforclass*”對(duì)話框,如圖2.11所示。該對(duì)話框左邊框中以“WM_”開頭列出所有可供響應(yīng)的事件消息,右上角框中列出項(xiàng)目中已作處理的響應(yīng)事件消息,右下角則列出某個(gè)事件消息是哪個(gè)類或?qū)ο蟮摹.?dāng)我們要處理某個(gè)事件時(shí),如“鼠標(biāo)左鍵按下”,我們?cè)趶棾龅膶?duì)話框中左邊雙擊“WM_LBUTTONDOWN”,將其添加到右邊的“Existingmessage/Eventhandlers:”列表框中,如圖2.11所示,然后選擇“AddandEdit”,則VC會(huì)自動(dòng)添加該事件的處理函數(shù),并將界面切換到處理函數(shù)位置,供程序員編寫相應(yīng)的處理代碼。2.11消息/事件處理對(duì)話框2.3在VC下實(shí)現(xiàn)OpenGL程序的編譯OpenGL包括*.h庫,*.lib庫和*.dll庫三部分。一般情況下,Windows操作系統(tǒng)已包含OpenGL的核心庫。設(shè)VC安裝在C:\ProgramFiles\下,則在VC++6.0中*.h核心庫存放在“C:\ProgramFiles\MicrosoftVisualStudio\VC98\Include\GL”中;*.lib核心庫存放在“C:\ProgramFiles\MicrosoftVisualStudio\VC98\Lib”中;*.dll核心庫存放在“C:\WINDOWS\system32”具有OpenGL所需的函數(shù)庫后,在VC++6的“Project”菜單下,選擇“Setting”項(xiàng),彈出“ProjectSetting”對(duì)話框,選擇“Link”項(xiàng),在“Libaray”欄目中加入OpenGL提供的函數(shù)庫:“opengl32.libglu32.libglaux.lib”。最后,在調(diào)用OpenGL函數(shù)的C++文件中將函數(shù)所在頭文件包含進(jìn)來,就可以使用OpenGL了。實(shí)驗(yàn)1Windows操作系統(tǒng)圖形開發(fā)基礎(chǔ)一、實(shí)驗(yàn)要求和目的掌握Windows圖形環(huán)境及圖形程序開發(fā)方法;掌握MFC應(yīng)用程序中OpenGL程序開發(fā)基本方法;掌握VC++程序設(shè)計(jì)方法。二、相關(guān)知識(shí)提要1.GDI工具的使用(1)GDI工具主要指MFC中各種GDI(圖形設(shè)備接口)函數(shù),包含了可用于繪制點(diǎn)、線、矩形、多邊形、橢圓、位圖以及文本的功能函數(shù)。VC中對(duì)其進(jìn)行封裝,形成GDI對(duì)象類,并派生出以下各類:CBitmap、CBrush、CPen、CFont、CPalette、CRgn。(2)在MFC類庫中,CPen類封裝了GDI的畫筆工具,CBrush類封裝了GDI的畫刷工具。在定義畫筆和畫刷工具時(shí),都要調(diào)用構(gòu)造函數(shù)創(chuàng)建默認(rèn)的畫筆(黑色,實(shí)線,寬度為一個(gè)像素)和畫刷(將封閉圖形內(nèi)部填充為白色)。繪圖時(shí)使用畫筆和畫刷步驟如下:①創(chuàng)建CPen類對(duì)象或CBrush類對(duì)象;②調(diào)用合適的成員函數(shù)初始化畫筆或畫刷;③將畫筆或畫刷對(duì)象選入當(dāng)前設(shè)備文本對(duì)象,并保存原先的畫筆或畫刷對(duì)象;④調(diào)用繪圖函數(shù)繪制圖形;⑤將原先的畫筆或畫刷對(duì)象選入設(shè)備文本對(duì)象,以便恢復(fù)原來狀態(tài)。(3)顏色的數(shù)據(jù)類型是COLORREF,表示RGB值是一個(gè)32位整數(shù),由RGB(紅,綠,藍(lán))的形式指定,每個(gè)分量值從0到255,0最低,255最高。3種顏色分量結(jié)合起來產(chǎn)生實(shí)際顏色。指定RGB值可以用手工(如0x00FF0000是純藍(lán)),也可以用宏RGB()指定,如RGB(255,0,0)為紅色。(4)GDI定義畫筆風(fēng)格與含義如表S1.1:表S1.1畫筆風(fēng)格與含義畫筆風(fēng)格含義畫筆風(fēng)格含義PS_DASH劃線,即虛線PS_INSIDEFRAME在邊界區(qū)域內(nèi)實(shí)線PS_DASHDOT點(diǎn)劃線PS_NULL空畫筆PS_DASHDOTDOT雙點(diǎn)劃線PS_SOLID實(shí)線PS_DOT點(diǎn)線(5)CBrush的成員函數(shù)CreateSolidBrush用顏色來初始化填充畫刷,函數(shù)原型如下:BOOLCreateSolidBrush(COLORREFcrColor);此外,還可調(diào)用成員函數(shù)CreateHatchBrush用某種影線來初始化填充畫刷。函數(shù)原型為:BOOLCreateHatchBrush(intnIndex,COLORREFcrColor);其中參數(shù)nIndex用于指定影線模式,其值如表S1.2,crColor用于指定畫刷顏色。表S1.2畫刷影線模式及含義陰影模式含義陰影模式含義HS_BDIAGONAL反斜線HS_FDIAGONAL斜線HS_CROSS十字線HS_HORIZONAL水平線HS_DIAGCROSS斜十字線HS_VERTICAL豎線(6)除了使用定制的畫筆和畫刷外,MFC中也庫存了一部分繪圖工具,使用時(shí)只需調(diào)用CDC成員函數(shù)SelectStockObject即可,函數(shù)原型是:virtualCGdiObject*SelectStockObject(intnIndex);如果調(diào)用成功,返回指向CGdiObject對(duì)象的指針(實(shí)際指向的對(duì)象是CPen或CBrush對(duì)象),否則返回NULL。nIndex是所要選入的庫存對(duì)象,對(duì)于畫筆和畫刷,值如表S1.3。表S1.3GDI庫存對(duì)象含義宏代碼庫存對(duì)象宏代碼庫存對(duì)象BLACK_BRUSH黑色畫刷NULL_BRUSH空畫刷(內(nèi)部不填充)DKGRAY_BRUSH深灰色畫刷WHITE_BRUSH白色畫刷GRAY_BRUSH灰色畫刷BLACK_PEN黑色畫筆HOLLOW_BRUSH透明窗口畫刷NULL_PEN空畫筆(什么也不畫)LTGRAY_BRUSH淺灰色畫刷WHITE_PEN白色畫筆2.Windows下開發(fā)OpenGL程序的基本方法(1)在MFC單文檔應(yīng)用程序中,視圖類用來顯示圖形,需要修改該類的成員函數(shù)代碼實(shí)現(xiàn)OpenGL繪圖,主要過程如下:①改造OnCreate函數(shù)開發(fā)OpenGL繪圖程序時(shí),需要設(shè)置像素格式。像素格式告訴OpenGL繪制風(fēng)格、顏色模式、顏色位數(shù)和深度位數(shù)等重要信息。Windows平臺(tái)下OpenGL提供了專門函數(shù)進(jìn)行處理??梢栽贠nCreate函數(shù)中定義像素格式,并創(chuàng)建一個(gè)OpenGL操作所必須的繪圖上下文RC(renderingcontext)。使用PIXELFORMATDESCRIPTOR結(jié)構(gòu)指定像素格式,使用wglCreateContext()函數(shù)創(chuàng)建繪圖上下文RC。②改造OnSize函數(shù)當(dāng)視圖發(fā)生變化時(shí),應(yīng)及時(shí)將新的客戶區(qū)尺寸通知OpenGL,才能夠正確在窗口客戶區(qū)域顯示三維場(chǎng)景的二維影像,通過命令glViewport完成該工作。③改造OnDestroy函數(shù)在OnDestory成員中用wglMakeCurrent()和wglDeleteContext()斷開OnCreate成員中RC與設(shè)備描述表DC的連接,并釋放RC所占資源。④改造OnDraw函數(shù)在OnDraw函數(shù)完成每次屏幕的繪制。(2)在每次繪制場(chǎng)景前,先要清除OpenGL顯示緩存中的信息,以免影響繪圖效果。用glClearColor設(shè)置屏幕背景顏色;用glClear清除顯示緩存。這兩個(gè)函數(shù)為:voidglClearColor(red,green,blue,alpha);//背景的RGBA信息voidglClear(mask);//清除標(biāo)志緩沖區(qū)mask參數(shù)如表S1.4所示:表S1.4OpenGL緩沖區(qū)代碼及含義緩沖區(qū)名稱緩沖區(qū)名稱顏色緩沖區(qū)GL_COLOR_BUFFER_BIT累加緩沖區(qū)GL_ACCUM_BUFFER_BIT深度緩沖區(qū)GL_DEPTH_BUFFER_BIT模板緩沖區(qū)GL_STENCIL_BUFFER_BIT三、實(shí)驗(yàn)內(nèi)容及步驟1.創(chuàng)建My2D項(xiàng)目和My3D項(xiàng)目建立兩個(gè)單文檔MFC項(xiàng)目,一個(gè)為My2D,另一個(gè)為My3D。My2D項(xiàng)目用于二維GDI繪圖;My3D項(xiàng)目用于三維OpenGL繪圖。2.用GDI工具繪制不同顏色、線型和線寬的直線在My2D項(xiàng)目中①在CMy2DView類中添加DrawLine函數(shù)如下:voidCMy2DView::DrawLine(CDC*pDC,CPointstartPoint,CPointendPoint,COLORREFcolor,intwidth,unsignedshorttype/*畫筆風(fēng)格*/){ CPen*pOldPen; CPennewPen;//創(chuàng)建一個(gè)新畫筆 newPen.CreatePen(type,width,color);//設(shè)置畫筆屬性并初始化畫筆 pOldPen=pDC->SelectObject(&newPen);//將新畫筆選進(jìn)當(dāng)前設(shè)備,并保存原畫筆 pDC->MoveTo(startPoint.x,startPoint.y);//將畫筆移到直線起點(diǎn) pDC->LineTo(endPoint.x,endPoint.y);//將畫筆移到直線終點(diǎn),實(shí)現(xiàn)繪制 pDC->SelectObject(pOldPen);//將原畫筆選進(jìn)當(dāng)前設(shè)備,恢復(fù)原來狀態(tài)}②在CMy2DView類中的OnDraw函數(shù)中調(diào)用DrawLine函數(shù)(粗體為添加部分),畫一條從(300,200)到(600,100),寬度為2,顏色為紅色的虛線。voidCMy2DView::OnDraw(CDC*pDC){ CMy2DDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc); DrawLine(pDC,CPoint(300,200),CPoint(600,100),RGB(255,0,0),2,PS_DASH);}3.用GDI工具繪制不同顏色的填充矩形①在CMy2DView類中添加DrawSolidRectangle函數(shù)如下:voidCMy2DView::DrawSolidRectangle(CDC*pDC,intleft,inttop,intright,intdown,COLORREFfilledcolor){CBrush*pOldBrush=NULL;CBrushSolidBrush;SolidBrush.CreateSolidBrush(filledcolor);//設(shè)置畫刷顏色,并初始化一個(gè)實(shí)畫刷pOldBrush=(CBrush*)pDC->SelectObject(&SolidBrush);pDC->Rectangle(left,top,right,down);//繪制矩形,參數(shù)分別為左上角點(diǎn)及右下角點(diǎn)x,y坐標(biāo)pDC->SelectObject(pOldBrush);}②在CMy2DView類中的OnDraw函數(shù)中調(diào)用DrawSolidRectangle函數(shù)(粗體為添加部分),繪制從左上角(10,20)到右下角(300,500),顏色為綠色的矩形。voidCMy2DView::OnDraw(CDC*pDC){ CMy2DDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc); DrawSolidRectangle(pDC,10,20,300,500,RGB(0,255,0));}4.創(chuàng)建OpenGL繪圖環(huán)境在My3D項(xiàng)目中①在CMy3DView頭文件中添加包含文件:#include<gl\glut.h>。②在CMy3DView中添加成員變量HGLRCm_hRC,CDC*m_pDC。③在CMy3DView中添加成員函數(shù)InitOpenGL如下:BOOLCMy3DView::InitOpenGL(){ staticPIXELFORMATDESCRIPTORpfd= { sizeof(PIXELFORMATDESCRIPTOR),//pfd大小 1,//結(jié)構(gòu)版本號(hào) PFD_DRAW_TO_WINDOW|//支持窗口 PFD_SUPPORT_OPENGL| //支持OpenGL PFD_DOUBLEBUFFER, //雙緩存 PFD_TYPE_RGBA,//RGBA顏色模式 24,//24位顏色深度 0,0,0,0,0,0,//colorbitsignored 0,//noalphabuffer 0,//shiftbitignored 0,//不使用累積緩存 0,0,0,0,//accumbitsignored 32,//32位Z緩沖 0,//不使用模板緩存 0,//noauxiliarybuffer PFD_MAIN_PLANE,//選擇主層面 0,//保留 0,0,0//layermasksignored }; //得到客戶區(qū)設(shè)備上下文 m_pDC=newCClientDC(this); if(m_pDC==NULL) { MessageBox("獲得設(shè)備上下文失敗!"); returnfalse; } intpixelFormat=::ChoosePixelFormat(m_pDC->GetSafeHdc(),&pfd); BOOLsuccess=::SetPixelFormat(m_pDC->GetSafeHdc(),pixelFormat,&pfd); if(!success) returnFALSE; //創(chuàng)建繪圖上下文RC m_hRC=::wglCreateContext(m_pDC->GetSafeHdc()); if(m_hRC==0) { MessageBox("繪圖上下文RC創(chuàng)建失敗!"); returnFALSE; } if(::wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC)==FALSE) { MessageBox("關(guān)聯(lián)當(dāng)前RC失敗!"); returnFALSE; } glShadeModel(GL_SMOOTH); //啟用光順渲染 glClearColor(0.0f,0.0f,0.0f,0.0f); //黑色背景 returnTRUE;}④在CMy3DView中添加OnCreate消息響應(yīng)函數(shù),并在其中調(diào)用InitOpenGL()函數(shù)。⑤在CMy3DView中添加OnSize消息響應(yīng)函數(shù)如下:voidCMy3DView::OnSize(UINTnType,intcx,intcy){ C3DView::OnSize(nType,cx,cy); if(0>=cx||0>=cy) return; //selectthefullclientarea ::glViewport(0,0,cx,cy);}⑥在CMy3DView中添加OnDestroy消息響應(yīng)函數(shù)如下:voidCMy3DView::OnDestroy(){ CView::OnDestroy(); ::wglMakeCurrent(NULL,NULL); ::wglDeleteContext(m_hRC); if(m_pDC)//釋放DC { deletem_pDC; m_pDC=NULL; }}⑦在CMy3DView中添加成員函數(shù)DrawOGLScene如下:voidCMy3DView::DrawOGLScene(){ glClear(GL_COLOR_BUFFER_BIT);//清顏色緩存 glLoadIdentity(); //在此處添加場(chǎng)景繪制代碼 glFinish();//強(qiáng)制發(fā)出的OpenGL命令完成執(zhí)行 SwapBuffers(m_pDC->GetSafeHdc());//將繪制好的后臺(tái)緩存內(nèi)容交換到前臺(tái)顯示}⑧在OnDraw()函數(shù)中調(diào)用DrawOGLScene()函數(shù)。5.OpenGL中繪制漸變?nèi)切卧贒rawOGLScene函數(shù)的“場(chǎng)景繪制代碼”處添加如下代碼:voidCMy3DView::DrawOGLScene(){…… //在此處添加場(chǎng)景繪制代碼//繪制漸變?nèi)切蝕lBegin(GL_TRIANGLES);//每三個(gè)頂點(diǎn)組成一個(gè)三角形glColor3f(1.0,0.0,0.0);//設(shè)置頂點(diǎn)顏色 glVertex3f(-1.0,0.0,0.0);//頂點(diǎn)坐標(biāo) glColor3f(0.0,1.0,0.0); glVertex3f(0.0,1.0,0.0); glColor3f(0.0,0.0,1.0); glVertex3f(1.0,0.0,0.0);glEnd();……}四、實(shí)驗(yàn)習(xí)題1、用GDI工具繪制不同顏色、寬度、線型邊框,不同填充模式及顏色的矩形。2、用GDI工具繪制不同顏色、寬度、線型的折線,折線端點(diǎn)用數(shù)組事先存儲(chǔ)。3、用GDI工具繪制不同顏色、寬度、線型邊框,不同填充模式及顏色的橢圓。4、用OpenGL在MFC應(yīng)用程序中繪制不同顏色的多邊形。實(shí)驗(yàn)2基本光柵圖形生成一、實(shí)驗(yàn)要求和目的了解MFC常用繪圖函數(shù);掌握用中點(diǎn)畫圓法繪制二次曲線的方法;掌握常用種子填充算法;掌握用OpenGL生成基本圖形的方法。二、相關(guān)知識(shí)提要1.常用MFC繪圖函數(shù)介紹繪圖函數(shù)都要求坐標(biāo)按邏輯坐標(biāo)給出。默認(rèn)時(shí),圖形坐標(biāo)系統(tǒng)的左上角位于(0,0)處,邏輯單位為像素。下面介紹常用CDC類的畫圖成員函數(shù),更多畫圖函數(shù)請(qǐng)參照MSDN。(1)設(shè)置像素(畫點(diǎn))COLORREFSetPixel(intx,inty,COLORREFcrColor);COLORREFSetPixel(POINTpoint,COLORREFcrColor);(2)設(shè)置當(dāng)前位置CPointMoveTo(intx,inty);CPointMoveTo(POINTpoint);(3)畫直線BOOLLineTo(intx,inty);BOOLLineTo(POINTpoint);(4)畫弧BOOLArc(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4);BOOLArc(LPCRECTlpRect,POINTptStart,POINTptEnd);邊界矩形由左上角參數(shù)(x1,y1)和右下角(x2,y2)或者lpRect定義,(x3,y3)或者ptStart是弧的起始點(diǎn),(x4,y4)或者ptEnd是弧的終止點(diǎn)。(5)畫矩形BOOLRectangle(intx1,inty1,intx2,inty2);BOOLRectangle(LPCRECTlpRect);(6)畫橢圓或圓BOOLEllipse(intx1,inty1,intx2,inty2);BOOLEllipse(LPCRECTlpRect);(7)畫多邊形BOOLPolygon(LPPOINTlpPoints,intnCount);參數(shù)lpPoints為多邊形頂點(diǎn)數(shù)組地址,nCount為指定數(shù)組的頂點(diǎn)數(shù)。(8)用指定畫刷填充一個(gè)矩形區(qū)域,但不畫邊線voidFillRect(LPCRECTlpRect,CBrush*pBrush);(9)用指定畫刷填充一個(gè)封閉區(qū)域BOOLFloodFill(intx,inty,COLORREFcrColor);參數(shù)(x,y)是填充開始點(diǎn)坐標(biāo),crColor是指定邊界顏色。該函數(shù)用當(dāng)前畫刷從邏輯點(diǎn)(x,y)開始填充某個(gè)crColor顏色邊界的區(qū)域,如果點(diǎn)(x,y)顏色為crColor,或者在區(qū)域外,則返回零。2.OpenGL生成基本圖形常用函數(shù)介紹(1)繪制點(diǎn)、線、多邊形OpenGL提供了描述點(diǎn)、線、多邊形的繪制機(jī)制。它們通過glBegin()函數(shù)和glEnd()函數(shù)配對(duì)完成。函數(shù)原型為:voidglBegin(GLenummode);voidglEnd();其中mode的取值決定了繪制圖形的類型,取值及含義如圖S2.1所示:圖S2.1幾何圖元類型圖形的頂點(diǎn)用glVertext2{fdsi},或者glVertex3{fdsi}指定二維或者三維頂點(diǎn)。{}里面字符表示頂點(diǎn)坐標(biāo)數(shù)據(jù)類型,f—float,d—double,s—short,i—int。如glVertex3f(x,y,z)表示該頂點(diǎn)xyz坐標(biāo)為float型。頂點(diǎn)函數(shù)必須放在glBegin()和glEnd()函數(shù)之間。繪制多邊形時(shí),頂點(diǎn)繪制的順序決定了多邊形面的方向,默認(rèn)情況下滿足右手螺旋法則,即頂點(diǎn)逆時(shí)針方向繪制時(shí),右手大拇指方向?yàn)檎?。?)定義點(diǎn)的大小voidglPointSize(GLfloatsize)(3)設(shè)置直線寬度voidglLineWidth(GLfloatwidth);(4)設(shè)置線型voidglLineStipple(GLintfactor,GLushortpattern);其中factor表示線型模式重復(fù)因子,說明了用二進(jìn)制點(diǎn)的重復(fù)次數(shù),pattern為線型,用二進(jìn)制來描述,1代表一個(gè)實(shí)點(diǎn),0代表該像素處不畫直線。為了啟動(dòng)線型,繪制前須在OpenGL中使用glEnable(GL_LINE_STIPPLE)函數(shù)使設(shè)置的線型有效。(5)多邊形面控制函數(shù)voidglPolygonMode(GLenumface,GLenummode);face控制多邊形的正面和背面的繪圖方式:GL_FRONT_AND_BACK,正面和反面都畫;GL_FRONT,只畫正面;GL_BACK,只畫反面。Mode控制繪點(diǎn)、線框或填充多邊形:GL_POINT,用有一定間隔的點(diǎn)填充;GL_LINE,只畫多邊形邊框;GL_FILL,填充多邊形。默認(rèn)值:glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)(6)三維物體繪制函數(shù)voidglutWireSphere(GLdoubleradius,Glintslices,Glintstacks);voidglutSolidSphere(GLdoubleradius,Glintslices,Glintstacks);voidglutWireCube(GLdoublesize);voidglutSolidCube(GLdoublesize);voidglutWireTorus(GLdoubleinnerRadius,GLdoubleouterRadius,Glintnsides,Glintrings);voidglutSolidTours(GLdoubleinnerRadius,GLdoubleouterRadius,Glintnsides,Glintrings);voidglutWireDodecahedron(GLdoubleradius);voidglutSolidDodecahedron(GLdoubleradius);voidglutWireCone(GLdoubleradius,GLdoubleheight,GLintslices,Glintstacks);voidglutSolidCone(GLdoubleradius,GLdoubleheight,GLintslices,Glintstacks);voidglutWireTeapot(GLdoublesize);voidglutSolidTeapot(GLdoublesize);以上每組三維物體可以采用線框(Wire)和實(shí)體(Solid)兩種渲染模式,依次為球體,立方體,環(huán),正十二面體,圓錐,茶壺。三、實(shí)驗(yàn)內(nèi)容及題目(1)建立2D折線類及對(duì)象①在VC++的My2D項(xiàng)目的類視圖中建立一個(gè)2D折線類C2DBrokenLine,含有成員變量顏色(COLORREFm_color)、頂點(diǎn)數(shù)量(intm_nVertexNum)、頂點(diǎn)表(CPointm_ptVertices[100])。②在CMy2DView頭文件中添加包含文件#include"2DBrokenLine.h"。③在CMy2DView頭文件中添加成員變量:C2DBrokenLinem_2dbrokenline。(2)建立2D圓類及對(duì)象在VC++的My2D項(xiàng)目的類視圖中建立一個(gè)2D圓類C2DCircle,含有成員變量顏色、圓心、圓半徑。仿造(1)的步驟②③在CMy2DView中添加對(duì)象m_2dcircle。(3)建立2D多邊形類及對(duì)象在VC++的My2D項(xiàng)目的類視圖中建立一個(gè)2D多邊形類C2DPolygon,含有成員變量顏色、頂點(diǎn)數(shù)量、頂點(diǎn)表。仿造(1)的步驟②③在CMy2DView中添加對(duì)象m_2dpolygon。(4)建立3D向量類在VC++的My3D項(xiàng)目的類視圖中建立一個(gè)3D向量類CVector3,含有x、y、z三個(gè)成員變量floatm_x,floatm_y,floatm_z。(5)建立3D多邊形類及對(duì)象在VC++的My3D項(xiàng)目的類視圖中建立一個(gè)3D多邊形類C3DPolygon,含有成員變量顏色、頂點(diǎn)數(shù)量、頂點(diǎn)表(CVector3m_ptVertices[100])。仿造(1)的步驟②③在CMy3DView中添加對(duì)象m_3dpolygon。另外,需將CVector3類的頭文件添加到C3Dpolygon類頭文件中。(6)建立3D茶壺類及對(duì)象在VC++的My3D項(xiàng)目的類視圖中建立一個(gè)3D茶壺類C3DTeapot,含有成員變量茶壺包圍球半徑floatm_fRoundRdius,茶壺位置CVector3m_position。仿造(5)的步驟在CMy3DView中添加對(duì)象m_3dteapot。(7)用GDI繪制2D折線在C2DBrokenLine類中定義成員函數(shù)voidDrawBrokenLinewithGDI(CDC*pDC),實(shí)現(xiàn)用GDI繪制折線。(8)用Bresenham算法繪制2D折線①在C2DBrokenLine類中定義成員函數(shù)voidDrawLinewithMidPoint(CDC*pDC,CPointstartPt,CPointendPt),實(shí)現(xiàn)用Bresenham算法繪制從點(diǎn)startPt到endPt繪制直線,算法中繪點(diǎn)函數(shù)用CDC類的成員函數(shù)SetPixel()。②在C2DBrokenLine類中定義成員函數(shù)voidDrawBrokenLinewithMidPoint(CDC*pDC),在該函數(shù)中實(shí)現(xiàn)通過調(diào)用DrawLinewithMidPoint函數(shù)完成折線的繪制。注意:(7)~(8)要判斷折線頂點(diǎn)數(shù)是否合法(<100),合法則繪制,否則不繪制,直接返回。(9)用GDI繪制2D圓(不填充)在C2DCircle類中定義成員函數(shù)voidDrawCirclewithGDI(CDC*pDC),實(shí)現(xiàn)用GDI繪制圓。(10)用中點(diǎn)畫圓算法繪制2D圓在C2DCircle類中定義成員函數(shù)voidDrawCirclewithMidPoint(CDC*pDC),實(shí)現(xiàn)用中點(diǎn)畫圓算法繪制的圓。算法中繪點(diǎn)函數(shù)用CDC類的成員函數(shù)SetPixel()。(11)用GDI畫刷填充2D圓在C2DCircle類中定義成員函數(shù)voidDrawSolidCirclewithGDI(CDC*pDC,CPointcenterPt,intradius),實(shí)現(xiàn)用GDI繪制實(shí)心圓。(12)種子填充算法填充2D圓在C2DCircle類中定義成員函數(shù)voidFillCirclewithSeed(CDC*pDC,CPointseed,COLORREFfilledcolor),實(shí)現(xiàn)用種子填充算法填充繪制的圓。算法中繪點(diǎn)函數(shù)用CDC類的成員函數(shù)SetPixel()。注意:(9)~(12)要判斷圓半徑是否合法(>0),合法則繪制,否則不繪,直接返回。(13)用GDI繪制2D多邊形(不填充)在C2DPolygon類中定義成員函數(shù)voidDrawPolygonwithGDI(CDC*pDC),實(shí)現(xiàn)用CDC類的Polygon函數(shù)繪制多邊形。(14)用OpenGL繪制線框3D多邊形在C3DPolygon類中定義成員函數(shù)voidDrawWirePolygonwithOpenGL(),實(shí)現(xiàn)用OpenGL繪制線框多邊形。(15)用OpenGL填充3D多邊形在C3DPolygon類中定義成員函數(shù)voidDrawSolidPolygonwithOpenGL(),實(shí)現(xiàn)用OpenGL繪制填充多邊形。注意:(13)~(15)要判斷多邊形頂點(diǎn)數(shù)是否合法,合法則繪制,否則不繪,直接返回。最后,在CMy2DView或CMy3DView的OnDraw()函數(shù)中調(diào)用相應(yīng)類對(duì)象繪制函數(shù),完成繪制。實(shí)驗(yàn)3圖形變換一、實(shí)驗(yàn)要求和目的掌握二維、三維圖形幾何變換原理及實(shí)現(xiàn)方法;掌握OpenGL圖形變換實(shí)現(xiàn)方法;掌握OpenGL三維圖形觀察、裁減方法;二、相關(guān)知識(shí)提要幾何變換均可表示成的形式,其中,P為變換前圖形的規(guī)范化齊次坐標(biāo),1.圖形幾何變換方法(1)點(diǎn)的變換將點(diǎn)表示為規(guī)范化齊次坐標(biāo)形式,然后乘以變換矩陣;(2)直線的變換直線的變換通過對(duì)直線兩端點(diǎn)進(jìn)行變換,從而改變直線的位置和方向。(3)多邊形的變換多邊形變換是將變換矩陣作用到每個(gè)頂點(diǎn)的坐標(biāo)位置,并按新的頂點(diǎn)坐標(biāo)值和當(dāng)前屬性設(shè)置來生成新的多邊形。(4)曲線的變換曲線的變換可以通過變換曲線上的每一點(diǎn)并依據(jù)這些點(diǎn)重新畫線來完成。但對(duì)某些特殊的曲線,該過程可以得到簡(jiǎn)化,如圓的平移和旋轉(zhuǎn)。2.常用圖形復(fù)合變換(1)相對(duì)任一參考點(diǎn)的幾何變換相對(duì)某個(gè)參考點(diǎn)作比例、旋轉(zhuǎn)幾何變換,其變換過程如下:①將參考點(diǎn)移至坐標(biāo)原點(diǎn),此時(shí)進(jìn)行平移變換;②針對(duì)原點(diǎn)進(jìn)行幾何變換;③進(jìn)行反平移,將參考點(diǎn)又移回原來位置。(2)相對(duì)任意方向的幾何變換相對(duì)任意方向作比例、旋轉(zhuǎn)幾何變換,其變換過程如下:①先進(jìn)行旋轉(zhuǎn)變換,使針對(duì)變換的方向與坐標(biāo)軸重合;②針對(duì)坐標(biāo)軸進(jìn)行幾何變換;③進(jìn)行反方向旋轉(zhuǎn),以回復(fù)到原來的方向。3.OpenGL坐標(biāo)變換機(jī)制(1)OpenGL三維圖形的顯示變換步驟如圖S3.1。圖S3.1OpenGL三維圖形的顯示變換步驟(2)OpenGL中與變換有關(guān)的數(shù)據(jù)結(jié)構(gòu)OpenGL實(shí)現(xiàn)了將物體的各個(gè)頂點(diǎn)通過各種變換矩陣的作用映射到屏幕上的過程。其中與變換有關(guān)的矩陣有ModelView矩陣、Projection矩陣。Projection矩陣描述怎樣從三維空間變換到屏幕坐標(biāo),而ModelView矩陣描述物體的旋轉(zhuǎn)、平移、縮放等變換。調(diào)用變換命令前,需聲明其后矩陣操作的對(duì)象,用命令glMatrixMode定義,原型為:voidglMatrixMode(GLenummode)當(dāng)mode為GL_MODELVIEW時(shí),表示對(duì)ModelView矩陣操作,如果為GL_PROJECTION,表示對(duì)Projection矩陣操作,系統(tǒng)默認(rèn)對(duì)ModelView矩陣操作。OpenGL矩陣堆棧用來保存和恢復(fù)矩陣的狀態(tài),用于具有層次結(jié)構(gòu)的模型繪制中,以提高繪圖效率,與變換有關(guān)的矩陣堆棧有ModelView矩陣堆棧和Projection矩陣堆棧。OpenGL提供glPushMatrix()和glPopMatrix()兩條命令進(jìn)行矩陣堆棧操作。(3)OpenGL中ModelView坐標(biāo)變換機(jī)制Model變換相當(dāng)于確定被攝物體在場(chǎng)景中擺放方式,相當(dāng)于幾何變換。View變換相當(dāng)于在照相時(shí)相機(jī)的位置和拍攝方向,相當(dāng)于坐標(biāo)變換,這兩者的操作是等價(jià)的,因而在OpenGL中用同一個(gè)ModelView矩陣表示。(4)OpenGL中ModelView變換方法進(jìn)行視點(diǎn)變換和模型變換前,必須調(diào)用glMatrixMode(GL_MODELVIEW),申請(qǐng)以下變換命令只能改變ModelView矩陣。Model變換函數(shù):平移變換:voidglTranslate{fd}(TYPEx,TYPEy,TYPEz);旋轉(zhuǎn)變換:voidglRotate{fd}(TYPEangle,TYPEx,TYPEy,TYPEz);縮放變換:voidglScale{fd}(TYPEx,TYPEy,TYPEz)。注意:以上角度單位為度。4.View變換函數(shù)View變換一般是平移和旋轉(zhuǎn)的組合。視點(diǎn)變換的實(shí)現(xiàn)可以有以下幾種方法,也可以直接使用視點(diǎn)在原點(diǎn),方向指向z軸負(fù)方向的默認(rèn)設(shè)置。①使用模型變換命令glTranslate*()和glRotate*()。②利用OpenGL應(yīng)用程序庫函數(shù)gluLookAt()定義視點(diǎn)位置和視線方向。gluLookAt()函數(shù)原型:voidgluLookAt(GLdoubleeyex,GLdoubleeyey,GLdoubleeyez,GLdoublecenterx,GLdoublecentery,GLdoublecenterz,GLdoubleupx,GLdoubleupy,GLdoubleupz)視點(diǎn)由參數(shù)eyex、eyey、eyez確定,觀察點(diǎn)由參數(shù)centerx、centery、centerz確定,參數(shù)upx、upy、upz指定向上的方向。5.OpenGL投影變換voidgluPerspective(GLdouble,fovy,GLdoubleaspect,GLdoublezNear,GLdoublezFar)通過指定x-z平面內(nèi)的視角大小及寬高比aspect=w/h來確定沿視線方向的棱錐,并通過指定遠(yuǎn)、近剪切面與視點(diǎn)間的距離來截?cái)嗬忮F,從而確定視景體大小。gluPerspective()只能建立沿視線方向關(guān)于x,y軸都對(duì)稱的視景體,zNear、zFar的值均為正值。三、實(shí)驗(yàn)內(nèi)容及步驟1.OpenGL透視投影觀察①三維觀察采用透視投影,在CMy3DView的OnSize消息響應(yīng)函數(shù)中繼續(xù)添加如下代碼:voidCMy3DView::OnSize(UINTnType,intcx,intcy){ CView::OnSize(nType,cx,cy); if(0>=cx||0>=cy) return; //selectthefullclientarea ::glViewport(0,0,cx,cy); GLdoubleaspect_ratio;//width/heightratio //計(jì)算寬高比 aspect_ratio=(GLdouble)cx/(GLdouble)cy; //選擇投影變換模式 ::glMatrixMode(GL_PROJECTION); ::glLoadIdentity(); //設(shè)置視景體 ::gluPerspective(45.0f,aspect_ratio,1.0f,1000.0f); //切換到模型視圖變換模式 ::glMatrixMode(GL_MODELVIEW); glLoadIdentity();}②修改CMy3DView中DrawOGLScene()函數(shù),放置照相機(jī)位置和視線方向:voidCMy3DView::DrawOGLScene(){ glClear(GL_COLOR_BUFFER_BIT); //設(shè)置攝像機(jī)位置和視線方向 gluLookAt(0,0,2,0,0,0,0,1,0); //此處添加場(chǎng)景渲染代碼 glFinish(); SwapBuffers(m_pDC->GetSafeHdc());}至此完成OpenGL中三維觀察的設(shè)置。四、實(shí)驗(yàn)習(xí)題(1)折線的平移、旋轉(zhuǎn)在C2DBrokenLine類里添加成員函數(shù)voidTranslateBrokenLine(intx,inty,intz),根據(jù)圖形幾何變換矩陣實(shí)現(xiàn)折線在GDI環(huán)境中的平移;在C2DBrokenLine類里添加成員函數(shù)voidRotateBrokenLine(CPointcenter,floatangle),根據(jù)圖形幾何變換矩陣實(shí)現(xiàn)折線在GDI環(huán)境中繞中心點(diǎn)center,逆時(shí)針旋轉(zhuǎn)angle角度。(2)圓的平移、旋轉(zhuǎn)、縮放在C2DCircle類里添加成員函數(shù)voidTranslateCircle(intx,inty,intz),根據(jù)圖形幾何變換矩陣實(shí)現(xiàn)圓在GDI環(huán)境中的平移;在C2DCircle類里添加成員函數(shù)voidRotateCircle(CPointcenter,floatangle),根據(jù)圖形幾何變換矩陣實(shí)現(xiàn)圓在GDI環(huán)境中繞中心點(diǎn)center,逆時(shí)針旋轉(zhuǎn)angle角度;在C2DCircle類里添加成員函數(shù)voidScaleCircle(CPointcenter,intxS,intyS,intzS),根據(jù)圖形幾何變換矩陣實(shí)現(xiàn)圓在GDI環(huán)境中以點(diǎn)center為中心,x,y,z方向縮放比例依次為xS,yS,zS的縮放。(3)多邊形的平移、旋轉(zhuǎn)、縮放在C2DPolygon類里添加成員函數(shù)voidTranslatePolygon(intx,inty,intz),根據(jù)圖形幾何變換矩陣實(shí)現(xiàn)多邊形在GDI環(huán)境中的平移;在C2DPolygon類里添加成員函數(shù)voidRotatePolygon(CPointcenter,floatangle),根據(jù)圖形幾何變換矩陣實(shí)現(xiàn)多邊形在GDI環(huán)境中繞中心點(diǎn)center,逆時(shí)針旋轉(zhuǎn)angle角度。在C2DPolygon類里添加成員函數(shù)voidScalePolygon(CPointcenter,intxS,intyS,intzS),根據(jù)圖形幾何變換矩陣實(shí)現(xiàn)多邊形在GDI環(huán)境中以點(diǎn)center為中心,x,y,z方向縮放比例依次為xS,yS,zS的縮放。(4)OpenGL中三維圖形的幾何變換在DrawOGLScene函數(shù)中添加glutWireTeapot函數(shù)繪制m_teapot,然后在glutWireTeapot函數(shù)前面添加OpenGL的Model變換函數(shù),觀察茶壺位置變化。實(shí)驗(yàn)4交互式繪圖技術(shù)一、實(shí)驗(yàn)要求和目的掌握MFC下菜單、鼠標(biāo)、鍵盤事件驅(qū)動(dòng)編程方法;掌握橡皮筋交互式繪圖技術(shù);掌握OpenGL下利用Model變換函數(shù),通過鼠標(biāo)鍵盤觀察三維場(chǎng)景。二、實(shí)驗(yàn)內(nèi)容及步驟1.用模態(tài)對(duì)話框在GDI環(huán)境中繪制2D圓①在CMy2DView類中添加成員變量UINTm_uDrawType,控制繪制圖元類型。m_uDrawType=0畫圓,m_uDrawType=1畫折線,m_uDrawType=2畫多邊形,在CMy2DView構(gòu)造函數(shù)中令m_uDrawType=0。②添加C2DCircle成員函數(shù)voidCreate(CPointcenter,UINTradius,COLORREFcolor),函數(shù)代碼如下:voidC2DCircle::Create(CPointcenter,UINTradius,COLORREFcolor){ m_nCenter=center;//圓心 m_uRadius=radius;//半徑 m_color=color;//圓的顏色}③切換到My2D項(xiàng)目下的“Resource(資源)”欄,選擇Menu下的ID_MAINFRAME,打開菜單編輯欄,增加“繪圖”菜單項(xiàng),在“繪圖”菜單下增加子菜單“圓”,ID為ID_DRAW_2D_CIRCLE。④鼠標(biāo)右擊“Resource(資源)”欄的“Dialog”文件夾,在彈出菜單中選擇“InsertDialog”,增加一個(gè)對(duì)話框。鼠標(biāo)右擊新增的對(duì)話框邊框,在彈出菜單中選擇“Properties(屬性)”,在屬性對(duì)話框中修改ID為“IDD_DIALOG_CIRCLE”,Caption(標(biāo)題)為“畫圓”。⑤在左邊“Control”工具欄中選擇工具,并將之拖動(dòng)到新增的畫圓對(duì)話框中,并命名為“半徑”;在“Control”工具欄中選擇工具,拖到畫圓對(duì)話框中,打開其屬性對(duì)話框后將ID改為“IDC_EDIT_RADIUS”。以同樣方法增加圓心坐標(biāo):“X坐標(biāo)”,“Y坐標(biāo)”,顏色分量:“RED”,“GREEN”,“BLUE”,ID分別為“IDC_EDIT_COORD_X”,“IDC_EDIT_COORD_Y”,“IDC_EDIT_COLOR_RED”,“IDC_EDIT_COLOR_GREEN”,“IDC_EDIT_COLOR_BLUE”。最后增加組框(GroupBox)控件,并將各控件布局如圖S4.1:圖S4.1畫圓對(duì)話框⑥右鍵單擊畫圓對(duì)話框,在彈出菜單中選擇“ClassWinzard…”,再選擇“Createanewclass”,確定后為畫圓對(duì)話框建立一個(gè)對(duì)話框類,類名為CDlgDrawCircle,基類為CDialog(默認(rèn))。確定后在打開的“MFCClasswizard”對(duì)話框中選擇“成員變量(MemberVariables)”頁面,雙擊除IDOK和IDCANCEL以外的每個(gè)控件ID號(hào),為各個(gè)控件添加相應(yīng)的成員變量,各變量命名和類型如表S4.1所示:表S4.1畫圓對(duì)話框成員變量表控件ID數(shù)據(jù)類型變量名數(shù)據(jù)范圍IDC_EDIT_COORD_Xintm_nCoord_XIDC_EDIT_COORD_Yintm_nCoord_YIDC_EDIT_RADIUSUINTm_uRadiusIDC_EDIT_REDUINTm_uRed0~255IDC_EDIT_GREENUINTm_uGreen0~255IDC_EDIT_BLUEUINTm_uBlue0~255⑦在CMy2DView的實(shí)現(xiàn)文件(My2DView.cpp)的文件頭部添加包含文件:#include"DlgDrawCircle.h"。右鍵單擊“繪圖”下的“圓”子菜單,在彈出菜單中,選擇“ClassWinzard…”,打開MFCClassWizard對(duì)話框,在“ObjectIDs:”列表框中選擇ID_DRAW_2D_CIRCLE,在“Classname:”下拉表框中選擇CMy2DView,在“Message:”列表框中雙擊COMMAND,在彈出的對(duì)話框中選擇“OK”,再選擇“EditCode”按鈕。這樣我們?yōu)椤皥A”添加了菜單響應(yīng)函數(shù)OnDraw2DCircle(),我們?cè)谄渲刑砑尤缦麓a:voidCMy2DView::On2DDrawCircle(){ CDlgDrawCircletheDlg;//創(chuàng)建一個(gè)繪圓對(duì)話框 if(theDlg.DoModal()==IDOK)//建立一個(gè)模態(tài)對(duì)話框,如果對(duì)話框?yàn)椤癘K”狀態(tài) {m_uDrawType=0;//畫圓 //將對(duì)話框里的值賦給CMy2DView類的圓對(duì)象 m_2dcircle.Create(CPoint(theDlg.m_nCoord_X,theDlg.m_nCoord_Y),theDlg.m_uRadius,RGB(theDlg.m_uRed,theDlg.m_uGreen,theDlg.m_uBlue)); Invalidate(TRUE); }}⑧修改CMy2DView類的OnDraw()函數(shù)代碼如下:voidCMy2DView::OnDraw(CDC*pDC){ CMy2DDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc); m_2dcircle.DrawCirclewithGDI(pDC);//畫圓}⑨編譯運(yùn)行。2.橡皮筋方式繪制2D折線實(shí)現(xiàn)功能:選擇菜單欄“繪圖/折線”菜單后,鼠標(biāo)左鍵按下開始繪制并確定折線頂點(diǎn),移動(dòng)鼠標(biāo)時(shí)以橡皮筋方式顯示下一段折線段位置,右鍵按下結(jié)束繪制。步驟:①在CMy2DView類的頭文件中添加成員變量如下:intm_nMouseLButtonDownNum;//記錄鼠標(biāo)左鍵點(diǎn)擊客戶區(qū)次數(shù)CPointm_TempLineStartPos;//交互式繪圖時(shí)折線段起點(diǎn)CPointm_TempMovePos;//交互式繪圖時(shí)鼠標(biāo)移動(dòng)點(diǎn)在CMy2DView類的構(gòu)造函數(shù)中令m_nMouseLButtonDownNum=0②切換到My2D項(xiàng)目下的“Resource(資源)”欄,選擇Menu下的ID_MAINFARME,打開菜單編輯欄,在“繪圖”菜單下增加子菜單“折線”,ID為ID_DRAW_2D_BROKENLINE。③利用ClassWinzard為“繪圖”下的“折線”子菜單在CMy2DVi
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度跨境電商平臺(tái)區(qū)域代理合同范本3篇
- 2024年生物醫(yī)藥企業(yè)股權(quán)收購(gòu)合同匯編3篇
- 淘寶找建筑課程設(shè)計(jì)
- 專題03 閱讀理解之推理判斷題(練習(xí))(解析版)
- 煉鋼廠部門崗位職責(zé)說明書
- 機(jī)電工程施工組織設(shè)計(jì)
- (一)高標(biāo)準(zhǔn)農(nóng)田施工方案
- 油條配方課程設(shè)計(jì)
- 糖果罐子手工課程設(shè)計(jì)
- 算法課程設(shè)計(jì)總結(jié)
- 2024年中國(guó)陶瓷碗盆市場(chǎng)調(diào)查研究報(bào)告
- ISO 56001-2024《創(chuàng)新管理體系-要求》專業(yè)解讀與應(yīng)用實(shí)踐指導(dǎo)材料之22:“8運(yùn)行-8.1運(yùn)行策劃和控制”(雷澤佳編制-2025B0)
- 2024-2030年中國(guó)硅肥行業(yè)規(guī)模分析及投資前景研究報(bào)告
- 電網(wǎng)行業(yè)工作匯報(bào)模板22
- 2024-2025學(xué)年一年級(jí)數(shù)學(xué)上冊(cè)期末樂考非紙筆測(cè)試題(二 )(蘇教版2024秋)
- 2024秋期國(guó)家開放大學(xué)??啤陡叩葦?shù)學(xué)基礎(chǔ)》一平臺(tái)在線形考(形考任務(wù)一至四)試題及答案
- HSE應(yīng)急預(yù)案(完整版)
- 2024-2024年江蘇省普通高中學(xué)業(yè)水平測(cè)試物理試卷(含答案)
- 如何高效學(xué)習(xí)學(xué)習(xí)通超星課后章節(jié)答案期末考試題庫2023年
- HCCDP 云遷移認(rèn)證理論題庫
- 臺(tái)大公開課--《紅樓夢(mèng)》筆記剖析
評(píng)論
0/150
提交評(píng)論