版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第5章交互繪圖技術(shù)5.1窗口系統(tǒng)和事件驅(qū)動模式5.2交互式的顯示控制技術(shù)5.3交互式的圖形生成技術(shù)5.4交互式的圖形編輯技術(shù)5.5OpenGL對圖形交互的支持5.1窗口系統(tǒng)和事件驅(qū)動模式Windows操作系統(tǒng)是一個窗口式的多任務(wù)操作系統(tǒng),在Windows環(huán)境下編寫應(yīng)用程序,采用事件驅(qū)動機(jī)制。傳統(tǒng)的MS-DOS程序主要采用順序的、關(guān)聯(lián)的、過程驅(qū)動的程序設(shè)計方法。一個程序是一系列預(yù)先定義好的操作序列的組合,它具有一定的開頭、中間過程和結(jié)束。程序直接控制事件和過程的順序。這樣的程序設(shè)計方法是面向程序而不是面向用戶的,交互性差,用戶界面不夠友好,因為它強(qiáng)迫用戶按照某種不可更改的模式進(jìn)行工作。它的基本模型如圖所示。DOS環(huán)境下編程模式
事件驅(qū)動程序設(shè)計模式對于需要用戶交互的應(yīng)用程序來說,事件驅(qū)動的程序設(shè)計有著過程驅(qū)動方法無法替代的優(yōu)點。它是一種面向用戶的程序設(shè)計方法,它在程序設(shè)計過程中除了完成所需功能之外,更多的考慮了用戶可能的各種輸入,并針對性的設(shè)計相應(yīng)的處理程序。它是一種“被動”式程序設(shè)計方法,程序開始運行時,處于等待用戶輸入事件狀態(tài),然后取得事件并作出相應(yīng)反應(yīng),處理完畢又返回并處于等待事件狀態(tài)。它的基本模型如圖所示。事件驅(qū)動程序設(shè)計模式Windows下基于消息的事件驅(qū)動編程消息MSG結(jié)構(gòu)是Windows的一種數(shù)據(jù)結(jié)構(gòu),包含消息的窗口來源、消息種類、與此消息相關(guān)的附加信息、消息發(fā)生時鼠標(biāo)的位置等。接收和處理消息的是窗口,每個窗口都有一個專門負(fù)責(zé)處理消息的“窗口函數(shù)”。MFC中的事件驅(qū)動編程
微軟基礎(chǔ)類庫(MFC:MicrosoftFoundationClass)是微軟為Windows程序員提供的一個面向?qū)ο蟮腤indows編程接口,它大大簡化了Windows編程工作。MFC通過定義一個消息與處理函數(shù)的對照表,實現(xiàn)了消息處理的分離編程。每當(dāng)產(chǎn)生一個事件,便可以通過這個對照表找到相應(yīng)的消息處理函數(shù),執(zhí)行這個函數(shù)便完成了相應(yīng)的功能;這樣,程序員不再需要編寫龐大的窗口函數(shù)。因此需要一類特殊的對象,每個對象負(fù)責(zé)在不同狀態(tài)之下根據(jù)自己的任務(wù)完成工作,稱這些類為功能類,具有以下共同特點:都具有接收鍵盤,鼠標(biāo)消息的外部接口都應(yīng)提供一個初始化工作的外部接口Initalize都應(yīng)提供一個做掃尾工作的外部接口Suspend都應(yīng)提供接收自己將被刪除的消息的外部接口Kill提供恢復(fù)臨時的場景的外部接口Draw提供外部接口以完成被重新喚醒之后需要進(jìn)行的操作WakeUp每個功能類有相同的祖先,設(shè)計為虛接口VirtualFunction這種機(jī)制可是實現(xiàn)模塊分解和分工寫作,實現(xiàn)思想:從BaseFunction派生出一個新類,重載其中某些接口就可以完成具體的功能每個從BaseFunction派生出的新類只需負(fù)責(zé)自己的工作每個不同的功能類可以由不同的的單獨開發(fā)而不影響系統(tǒng)的集成文檔類(MFC體系)中設(shè)置功能類對象的隊列,包含當(dāng)前正在運轉(zhuǎn)的功能類對象和之前運轉(zhuǎn)過的對象從一種狀態(tài)A轉(zhuǎn)換到另一種狀態(tài)B需要傳劍一個新的功能類的對象b(B類對象),然后將b作為參數(shù)調(diào)用文檔的一個外部接口SetCurrentFunction,完成狀態(tài)轉(zhuǎn)換SetCurrentFunction:調(diào)用被掛起對象的Kill外部接口;調(diào)用隊列中當(dāng)前功能類對象的Suspend外部接口;最后調(diào)用b的外部接口Initalize,將b壓進(jìn)隊列,成為當(dāng)前功能類對象當(dāng)視圖接受到鼠標(biāo)鍵盤消息,將此消息分發(fā)給文檔類中維護(hù)的當(dāng)前功能類對象。5.2交互式的顯示控制技術(shù)全景顯示旋轉(zhuǎn)平移縮放
本節(jié)內(nèi)容為交互繪圖平臺與顯示相關(guān)的控制技術(shù),以上機(jī)實現(xiàn)為主。場景充滿窗口的控制方法//得到場景分布區(qū)域的寬度ExtendPoint3DMax,Min;PSceneData->GetBox(Max,Min);//設(shè)置視距viewDisatance=Max.Distance(&Min)*15;//求出場景中心點middlePoint,作為顯示中心點,保證場景能夠顯示在屏幕中心middlePoint=(Max+Min)/2;//求出場景分布區(qū)域x方向的長度dX_Extend和y方向的長度dY_ExtendPSceneData->GetBox(Max,Min);doubleExtend=Max.Distance(&Min);doubledX_Extend=Extend;doubledY_Extend=Extend;//再根據(jù)窗口的寬高比及Y方向的長度,得到X方向的適合窗口寬高比的長度dTmpX_ExtendDoubledTmpX_Extend=dY_Extend*m_dAspectRatio;//設(shè)置near平面和far平面nearestPlaneDistance=viewDistance-Extend/2;farestPlaneDistance=viewDistance+Extend/2;//設(shè)置視寬為X方向長度及Y方向的適合窗口寬高比的長度中小者//保證場景在X方向及Y方向都不會超出視景體viewWidth=max(dX_Extend,dTmpX_Extend)/1.1;//刷新窗口Invalidate();OnLButtonDown(msg){ m_LeftButtonDown=TRUE; m_LeftDownPos=GetMouseLocation(); m_CenterPoint=GetCenterPont(); m_ViewPoint=GetViewPoint();}OnLButtonUp(msg){ m_LeftButtonDown=FALSE;}OnMouseMove(msg){ intdx,dy; dx=m_LeftDownPos.x-GetMouseLocation().x; dy=m_LeftDownPos.y-GetMouseLocation().y; m_LeftDownPos=GetMouseLocation(); VP=m_ViewPoint-m_CenterPoint; doublealfa=3.14*dx/GetClientRect().right; SetViewDirection()VP; m_ViewPoint=GetViewPoint();
Invalidate();}m_LeftButtonDown用來標(biāo)志鼠標(biāo)左鍵是否已被按下。m_LeftDownPos記錄上次鼠標(biāo)移動事件中鼠標(biāo)的位置,用來計算兩次鼠標(biāo)移動的距離。m_CenterPoint,Point3D類型,顯示中心點的坐標(biāo)m_ViewPoint,Point3D類型,視點的位置當(dāng)按下鼠標(biāo)左鍵,旋轉(zhuǎn)操作開始:設(shè)標(biāo)志m_LeftButtonDown為真,表示已經(jīng)處于旋轉(zhuǎn)狀態(tài);記下此時鼠標(biāo)指針的位置,放在m_LeftDownPos中,用來在鼠標(biāo)移動事件中計算兩次鼠標(biāo)位置的移動距離,從而計算出場景旋轉(zhuǎn)的尺度;將此時場景的顯示中心點記入m_CenterPoint中,將視點位置記入m_ViewPoint中。當(dāng)鼠標(biāo)移動時,旋轉(zhuǎn)功能類首先判斷鼠標(biāo)左鍵是否已按下,這可以根據(jù)m_LeftButtonDown的值來確定。若鼠標(biāo)左鍵未按下,則不做任何處理,否則,做如下工作:分別計算上次鼠標(biāo)位置與現(xiàn)在鼠標(biāo)位置在x,y方向的距離,根據(jù)這兩個距離計算場景應(yīng)旋轉(zhuǎn)的尺度,然后按照這個尺度將視圖原來的實現(xiàn)方向(視點減去參考點所得向量)進(jìn)行旋轉(zhuǎn),得到新的視線方向VP,并將視圖的視線方向修改為新的值。然后刷新視圖。當(dāng)視圖刷新時,會根據(jù)視點、顯示中心點、視線方向等參數(shù)自動調(diào)整場景的外觀。當(dāng)鼠標(biāo)左鍵抬起時,表示旋轉(zhuǎn)動作結(jié)束。旋轉(zhuǎn)功能類將標(biāo)志m_LeftButtonDown的值設(shè)置FALSE平移操作:OnLButtonDown(msg){ m_LeftButtonDown=TRUE; //確認(rèn)鼠標(biāo)左鍵是否已被按下。
oldCenterPoint=GetCenterPont();//中心點的位置
m_LeftDownPos=GetMouseLocation();//上次鼠標(biāo)移動事件中鼠標(biāo)的位置}OnLButtonUp(msg){ m_LeftButtonDown=FALSE;}OnMouseMove(msg){ if(m_LeftButtonDown) {MouseLocation=GetMouseLocation(); oldPoint=GetWorldCrdByScreenCrd(m_LeftDownPos); newPoint=oldCenterPoint+(GetWorldCrdByScreenCrd(MouseLocation))-oldPoint; Invalidate(); }}設(shè)標(biāo)志m_LeftButtonDown為真,表示已經(jīng)處于旋轉(zhuǎn)狀態(tài);記下此時鼠標(biāo)指針的位置,放在m_LeftDownPos中,用來在鼠標(biāo)移動事件中計算兩次鼠標(biāo)位置的移動距離,從而計算出視圖平移的尺度;將此時場景的顯示中心點記入oldCenterPoint中當(dāng)鼠標(biāo)移動時,視圖平移功能類首先判斷鼠標(biāo)左鍵是否已按下,這可以根據(jù)m_LeftButtonDown的值來確定。若鼠標(biāo)左鍵按下,計算上次鼠標(biāo)位置對應(yīng)的世界坐標(biāo),計算本次鼠標(biāo)位置對應(yīng)的世界坐標(biāo),求得兩次鼠標(biāo)位置在世界坐標(biāo)系中的距離向量,將此向量加到場景的顯示中心點上,得到場景新的顯示中心點。最后刷新場景??s放操作OnLButtonDown(msg){ m_LeftButtonDown=TRUE; //確認(rèn)鼠標(biāo)左鍵是否已被按下。
m_LeftDownPos=GetMouseLocation();//上次鼠標(biāo)移動事件中鼠標(biāo)的位置
oldWidth=GetCenterWidth();//縮放之前視口的寬度}OnLButtonUp(msg){ m_LeftButtonDown=FALSE;}OnMouseMove(msg){ if(m_LeftButtonDown) { dy=m_LeftDownPos.y-GetMouseLocation().y; ScalingFactor=dy/msg.GetView()->GetClientRect().bottom; newWidth=oldWidth*(1+ScalingFactor); SetViewWidth(newwidth); InvalidateRect(NULL,FALSE); }}5.3交互式的圖形生成技術(shù)
坐標(biāo)的輸入技術(shù)將二維計算機(jī)屏幕的鼠標(biāo)位置轉(zhuǎn)換為三維世界坐標(biāo)。
橡皮筋技術(shù)實現(xiàn)橡皮筋技術(shù)主要有兩種方法:基于異或操作的橡皮筋技術(shù);基于緩沖區(qū)的橡皮筋技術(shù);5.4交互式的圖形編輯技術(shù)利用鼠標(biāo)動作來改變圖形選中圖形的方法5.4交互式的圖形編輯技術(shù)5.4交互式的圖形編輯技術(shù)圖形元素拾取辦法:靜態(tài)選擇功能類動態(tài)選擇功能類5.4交互式的圖形編輯技術(shù)靜態(tài)選擇功能類偽代碼實現(xiàn):(1)構(gòu)造函數(shù)m_pElementSet=pElementSet;//接收外部提供的待選擇圖元集合m_pElement=pElement;//接受外部提供的預(yù)選取對象If(m_pElement!=NULL)SetSelectedElement(m_pElement)//將用戶指定的默認(rèn)選中元素賦給成員變量,并高亮顯示默認(rèn)被選中元素5.4交互式的圖形編輯技術(shù)(2)數(shù)據(jù)成員ElementSet*m_pElementSet;//圖形元素集合,將從這些圖元中挑出被選中者,放到m_pElement中Element*m_pElement;//將被選中的圖元放在這個成員變量中(3)鼠標(biāo)左鍵處理//利用某種機(jī)制從待選擇元素集合中選擇出鼠標(biāo)指向的圖形元素Element*pEI=GetElementFromSelection(m_pElementSet,GetMouseLocation());If(pEI==m_pSelectedElement)return;//恢復(fù)屏幕背景,然后高亮顯示被選中的元素。If(pEI!=NULL)SetSelectedElement(pEI);5.4交互式的圖形編輯技術(shù)動態(tài)選擇功能類(1)數(shù)據(jù)成員ElementSet*m_pElementSet;//圖形元素集合,將從這些圖元中挑出被選中者,放到m_pElement中Element*m_pElement;//將被選中的圖元放在這個成員變量中(2)鼠標(biāo)移動處理//利用某種機(jī)制從待選擇元素集合中選擇出鼠標(biāo)指向的圖形元素Element*pEI=GetElementFromSelection(m_pElementSet,GetMouseLocation());If(pEI==m_pSelectedElement)return;If(pEI!=NULL)SetSelectedElement(pEI);5.4交互式的圖形編輯技術(shù)5.5OpenGL對圖形交互的支持三維坐標(biāo)輸入--OpenGL提供反向坐標(biāo)變換(gluUnProject)實現(xiàn)橡皮筋技術(shù)--OpenGL的雙緩存機(jī)制三維圖形的編輯及三維目標(biāo)實體的拾?。璒penGL提供了一種簡單直觀的選擇機(jī)制,能夠很容易的實現(xiàn)三維場景中任一圖形元素的選取。
5.5OpenGL對圖形交互的支持
用OpenGL的反向坐標(biāo)變換實現(xiàn)三維坐標(biāo)輸入
函數(shù)gluUnProject能夠?qū)indows屏幕坐標(biāo)轉(zhuǎn)換為場景中的三維世界坐標(biāo)。該函數(shù)需要指定如下參數(shù):視口的原點(X,Y坐標(biāo))及視口寬度(width)與高度(height)當(dāng)前顯示三維場景所使用的模型視圖變換矩陣(TheModelviewMatrix)當(dāng)前顯示三維場景所使用的投影變換矩陣(TheProjectionMatrix)Windows窗口坐標(biāo)存儲三維坐標(biāo)的變量(posX,posY,posZ)5.5OpenGL對圖形交互的支持視口信息:獲得視口左上角坐標(biāo)(x,y)和視口寬度
width及高度height Glintviewport[4];//存儲視口相關(guān)信息glGetIntegerv(GL_VIEWPORT,viewport);//檢索(x,y,width,height)調(diào)用成功后viewport數(shù)組四個元素將分別為x,y,width,height模型視圖變換矩陣:OpenGL圖元頂點的世界坐標(biāo)如何變換到視坐標(biāo)。
GLdoublemodelview[16];//存儲模型視圖變換矩陣的16個值
glGetDouble(GL_MODELVIEW_MATRIX,modelview) //檢索模型視圖矩陣5.5OpenGL對圖形交互的支持投影矩陣:將頂點的視坐標(biāo)變換為剪裁坐標(biāo)
GLdoubleprojection[16];//存儲投影矩陣的16個值
glGetDouble(GL_PROJECTION_MATRIX,projection) //檢索模型視圖矩陣
5.5OpenGL對圖形交互的支持Windows屏幕坐標(biāo):為要變換撐三維坐標(biāo)的數(shù)據(jù)來源,了解當(dāng)前鼠標(biāo)的位置CPointmouse;::GetCursorPos(&mouse);ScreenToClient(hWnd,&mouse);GLfloatwinX,winY,winZ;winX=(float)mouse.x;winY=(float)mouse.y;因為Windows窗口(0,0)從左上角開始,而OpenGL從左下角開始,所以winY=(float)viewport[3]-winY;winZ:通過glReadPixel(winX,winY,1,1,GL_DEPTH_COMPONENT,GL_GLOAT,&winZ)得到5.5OpenGL對圖形交互的支持存儲三維坐標(biāo)的變量進(jìn)行方向坐標(biāo)變換實現(xiàn)三維坐標(biāo)輸入的完整子程序:Point3DGetOGLPos(intx
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025女方離婚協(xié)議書
- 運動障礙性腦癱病因介紹
- 質(zhì)量策劃方案20241219
- (案例)標(biāo)準(zhǔn)件項目立項報告
- 2022-2023學(xué)年天津市高一(上)期末語文試卷
- 2022-2023學(xué)年天津四中高二(上)期末語文試卷
- 重慶2020-2024年中考英語5年真題回-學(xué)生版-專題07 閱讀理解之說明文
- 2023年碳酸丙烯酯項目籌資方案
- 2023年美容項目籌資方案
- 2023年大功率激光傳輸石英光纖項目籌資方案
- 關(guān)于市場化工具及其在中國的運用概述
- 監(jiān)控維保報告
- 足部健康宣教課件
- 生產(chǎn)準(zhǔn)備部進(jìn)出口報關(guān)員關(guān)鍵業(yè)績考核指標(biāo)(KPI)
- TSZSA 032-2023 SMD 塑料載帶技術(shù)規(guī)范
- 應(yīng)用文寫作《通知》課件 2023-2024學(xué)年高教版中職語文基礎(chǔ)模塊下冊
- 車險續(xù)保率分析報告
- 基于Android的天氣預(yù)報系統(tǒng)的設(shè)計與實現(xiàn)
- 省級代理合同
- 精神科患者飲食健康宣教知識
- 鄉(xiāng)村小學(xué)勞動課校本教材
評論
0/150
提交評論