《計算機圖形學基礎》課件第10章_第1頁
《計算機圖形學基礎》課件第10章_第2頁
《計算機圖形學基礎》課件第10章_第3頁
《計算機圖形學基礎》課件第10章_第4頁
《計算機圖形學基礎》課件第10章_第5頁
已閱讀5頁,還剩179頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第10章OpenGL程序設計基礎10.1

OpenGL概述

10.2基于OpenGL的基本圖形繪制

10.3基于VC++的OpenGL坐標變換

10.4用OpenGL生成曲線和曲面

10.5

OpenGL的光照處理

10.6

OpenGL對交互繪圖的支持

習題10

10.1

OpenGL概述

10.1.1

OpenGL編程的兩個基本特點

在Windows環(huán)境中編寫程序,一般具有兩個特點:采用事件驅動方式和面向對象方法編寫應用程序。

在PC的DOS操作系統(tǒng)時代,DOS操作系統(tǒng)每次只能接受一個用戶程序,然后把計算機CPU的控制權交給應用程序,應用程序執(zhí)行完畢之后,再把CPU的控制權交回DOS。通過閱讀這種應用程序的程序清單,用戶可以很清楚地了解該程序的邏輯執(zhí)行順序。它的缺點是用戶開發(fā)新的程序時編程的工作量大,應用程序會獨占CPU的資源,這種程序不

便在多任務操作系統(tǒng)中使用。最簡單的事件驅動方式也就是中斷處理方式,即由操作系統(tǒng)用中斷方式統(tǒng)一管理計算機的外部設備,每當外設發(fā)生一個中斷時操作系統(tǒng)分清該中斷產生的數據與類型,然后把對該事件處理的中斷服務程序交用戶程序處理。該事件處理完畢后,操作系統(tǒng)把CPU的控制權收回并等待新的事件發(fā)生,如此循環(huán)。故在這種方式下操作系統(tǒng)可以同時接受多個用戶的應用程序。Windows操作系統(tǒng)就是采用這種方式處理各種應用程序的。

Windows是一個多任務的操作系統(tǒng),其編程風格轉向采用事件驅動。Windows操作系統(tǒng)統(tǒng)一接收管理計算機中發(fā)生的所有事件,并負責消息的發(fā)送;而用戶程序主要根據這些消息,分別處理每個消息對應事件的響應,此時,用戶程序主要由多個事件的響應程序等組成;同時,Windows操作系統(tǒng)還為應用程序編寫了發(fā)送消息的函數,用戶可以通過發(fā)送消息,經Windows操作系統(tǒng)來間接控制用戶程序的所有分支都得到有效的執(zhí)行。從這個意義上說,產生事件或發(fā)送消息是面向對象程序得到執(zhí)行處理的唯一機會。這種程序實現方法的好處是每個用戶程序只占用事件處理等少量的CPU時間,剩余時間把對CPU的控制權都交還給操作系統(tǒng),由此,操作系統(tǒng)可以騰出時間處理其他用戶的程序,這樣就使得鼠標、鍵盤、窗口等事件的處理變得非常簡單,且編程工作量小。但是這種編程方式也使得程序執(zhí)行的邏輯關系變得相對復雜,閱讀理解相對困難。另外,目前Windows程序在實時控制中的穩(wěn)定性還有待提高。10.1.2

OpenGL的主要功能

1.OpenGL基本操作

雖然客觀事物的形狀千變萬化,但用計算機將之描述,只需把一系列基本操作組合起來即可。OpenGL提供了以下基本操作:

(1)繪制物體:真實世界里的任何物體都可以在計算機中用簡單的點、線、多邊形來描述,OpenGL提供了豐富的基本圖元繪制命令,從而可以方便地繪制物體。

(2)變換:無論多么復雜的圖形都是由基本圖元組成并經過一系列變換來實現的,OpenGL提供了一系列基本的變換,如取景變換、模型變換、投影變換及視口變換。

(3)光照處理:正如自然界不可缺少光一樣,繪制有真實感的三維物體必須做光照處理。

(4)著色:OpenGL提供了兩種物體著色模式,一種是RGBA顏色模式,另一種是顏色索引模式。

(5)反走樣:在OpenGL繪制圖形過程中,由于使用的是位圖,所以繪制出的圖像邊緣會出現鋸齒形狀,稱為走樣。為了消除這種缺陷,OpenGL提供了點、線、多邊形的反走樣技術。

(6)融合:為了使三維圖形更加具有真實感,經常需要處理半透明或透明的物體圖像,這就需要用到融合技術。

(7)霧化:正如自然界中存在煙霧一樣,OpenGL提供了“fog”的基本操作來達到對場景進行霧化的效果。

(8)位圖和圖像:在圖形繪制過程中,位圖和圖像操作是非常重要的方面。OpenGL提供了一系列函數來實現位圖和圖像的操作。

(9)紋理映射:在計算機圖形學中,把包含顏色、alpha值、亮度等數據的矩形數組稱為紋理。紋理映射可以理解為將紋理粘貼在所繪制的三維模型表面,以使三維圖形顯得更生動。

(10)動畫:出色的動畫效果是OpenGL的一大特色。OpenGL提供了雙緩存技術來實現動畫繪制,即在顯示前臺緩存中圖像的同時,后臺緩存繪制第二幅圖像;當后臺繪制

完成后,后臺緩存中的圖像就顯示出來,此時原來的前臺緩存開始繪制第三幅圖像。如此循環(huán)往復,以增加圖像的輸出速度。

2.OpenGL函數及數據類型

OpenGL的庫函數分為四類:核心庫函數、實用庫函數、輔助庫函數和專用庫函數。

(1)核心庫函數:OpenGL有115個核心庫函數,均以“gl”為前綴,它們提供了最基本的功能,比如實現三維建模、建立光照模型、反走樣和紋理映射等功能。

(2)實用庫函數:OpenGL的實用庫函數有43個,均以“glu”為前綴,它們在核心函數的上層。其實質是對核心函數進行組織和封裝,提供比較簡單的函數接口和用法,可減輕開發(fā)者的編程負擔。

(3)輔助庫函數:OpenGL的輔助庫函數有31個,均以“aux”為前綴。應用程序只能在Win32環(huán)境中使用這些函數,可移植性較差,在Windows應用程序中一般用于窗口管

理、輸入/輸出處理以及繪制一些簡單的三維形體。

(4)專用庫函數:專用庫函數由6個以“wgl”為前綴的函數和5個Win32API函數組成?!皐gl”函數用于連接Windows和OpenGL、初始化窗口,能夠使用OpenGL在窗口中進行繪制;Win32API函數用于處理像素存儲格式、雙緩存等函數的調用。

OpenGL中函數的命名規(guī)則為“前綴—詞根—數字后綴—類型后綴”。前綴表明函數的類型;詞根為函數的功能描述;數字后綴可以是“2”、“3”、“4”,表明參數向量的維數;類型后綴可以是“b”、“i”、“f”等,表明函數參數的數據類型。例如函數“glColor3f”:“gl”表明這個函數屬于核心函數,“Color”表明它用來設置當前顏色,“3”表明函數需要3個參數,“f”表明函數的每一個參數都為浮點型數值。

OpenGL定義的常量都以GL開頭,并且所有字母都大寫,單詞之間以下劃線來分隔,例如GL_COLOR_BUFFER_BIT。

3.OpenGL的緩沖區(qū)

OpenGL進行圖形顯示時需要用到4個緩沖區(qū),即顏色緩存、深度緩存、模板緩存和累積緩存。這里只簡單介紹其概念,使用方法將在后面介紹。

1)顏色緩存

顏色緩存由紅、綠、藍、alpha位平面組成,有前緩存、后緩存、左前緩存、右前緩存、左后緩存、右后緩存等幾種。其中左前緩存是必需的顏色緩存,前緩存是可見緩存,后緩存是不可見緩存。前后緩存技術可實現動畫操作。

2)深度緩存

深度緩存也叫Z-buffer,記錄每個像素點所對應的物體點到視點的距離,由此決定表面的可見性,用于物體的消隱。

3)模板緩存和累積緩存

模板緩存和累積緩存主要用于圖形的特殊效果繪制。模板緩存存放像素的模板字,用于控制像素是否被改寫,實現禁止在屏幕的某些區(qū)域繪圖。模板緩存可用于多種復雜圖形的繪制(凸/凹區(qū)域、凹多邊形等)、屏蔽屏幕區(qū)域、遮擋物體、制作物體的交集等。累積緩存是一系列繪制結果的積累,可用來實現場景的反走樣、景深模擬和運動模糊等。10.1.3

OpenGL繪圖程序開發(fā)方法

利用VC++和OpenGL來開發(fā)繪圖程序,需要構造一個基于消息的Windows窗口,在這個窗口中使用OpenGL的函數進行繪制和渲染。有兩種構造窗口的方法,一種是應用OpenGL的GLU和AUX函數庫,另一種是使用VC++的MFC。

使用輔助函數庫和使用MFC來構造應用程序框架的不同之處在于,MFC應用程序是由Windows來分發(fā)消息,在消息響應函數中處理初始化、設置繪圖場景和繪制圖形的工作;而使用輔助函數庫則是編寫回調函數,然后在主函數中使用auxReshapeFunc和auxMainLoop調用回調函數來實現消息的循環(huán)。

下面通過一個繪制顏色漸變的三角形的實例,來說明用VisualC++開發(fā)OpenGL繪圖程序的方法。

1.利用OpenGL的GLU和AUX的繪圖實例

1)新建工程

在VC++中的“File”菜單中選擇“New”命令,在彈出的對話框中選擇項目的類型為“Win32ConsoleApplication”,然后輸入項目的名字“FirstAuxOpenGL”。接著單擊“OK”按鈕進入應用程序向導對話框,在其中選擇項目的類型為“AnEmpetyProject”,即一個空的項目。選擇完成以后,單擊“Finish”按鈕,結束項目設置,即可自動生成應用程序的框架。

2)添加文件

單擊 按鈕,選擇“File”菜單中的“另存為”項,將其保存為“FirstAuxOpenGL.c”文件。右鍵單擊“SourceFiles”,再單擊“AddFilestoFolder”即可把文件“FirstAuxOpenGL.c”添加到項目中。接下來,在FirstAuxOpenGL.c文件中添加下列代碼:函數auxReshapFunc和函數auxMainLoop的參數是兩個回調函數(使用CALLBACK聲明),在這兩個函數中分別處理場景設置和繪制操作。

初始化函數、設置場景函數、繪制函數和主函數這4個主要函數構成了使用輔助函數庫創(chuàng)建OpenGL應用程序的框架。

3)項目設置

在“Project”菜單中選擇“Settings”,再單擊“Link”,彈出如圖10-1所示的對話框。在“對象/庫模塊”編輯框中添加在程序鏈接中用到的3個函數庫:OpenGL32.lib、glu32.lib和glAux.lib。

運行程序,效果如圖10-2所示。圖10-1在工程中加入鏈接庫函數圖10-2

FirstAuxOpenGL的運行結果

2.使用MFC和專用函數的繪圖實例

在開發(fā)過程中,需要使用MFC所提供的基于Windows的消息發(fā)送機制的“文檔—視”結構來組織應用程序。這里不能使用輔助函數,但可以應用OpenGL所提供的專用函數來與MFC應用程序相銜接。

1)新建工程

在VC++的“File”菜單中選擇“New”命令,在彈出的對話框中選擇項目的類型為“MFCAppwizard[exe]”,輸入項目的名字“FirstMfcOpenGL”,然后單擊“OK”按鈕進入應用程序向導對話框。創(chuàng)建單文檔應用程序,然后單擊“Finish”按鈕,接受默認設置,即可自動生成應用程序的框架。

2)添加初始化及終止代碼

在視類CFirstMfcOpenGLView的頭文件CFirstMfcOpenGLView.h中加入頭文件“gl.h”和“glu.h”以及兩個記錄繪圖設備的成員變量,如下列程序所示:在“View”菜單中選擇“ClassWizard”命令,彈出如圖10-3所示的“類向導”對話框。在該對話框的“Classname”下拉列表框中選擇視類CFirstMfcOpenGLView,然后在“Messages”列表框中選擇WM_CREATE、WM_DESDROY和WM_SIZE這三個消息,為它們添加對應的消息響應函數OnCreate、OnDestroy和OnSize。圖10-3

FirstMfcOpenGL工程中的“類向導”對話框接下來,在OnCreate函數中添加如下初始化代碼:在OnDestroy函數中添加如下代碼:在PreCreateWindow函數中對窗口的風格進行設置:

3)根據窗口大小設置場景

在MFC應用程序中,窗口的位置及大小的改變都會激發(fā)一個WM_SIZE消息,在視類的消息響應函數OnSize中執(zhí)行它,因此在OnSize中應該添加響應的處理,根據窗口大小設置場景,代碼如下:4)添加繪制三角形的代碼

繪制三角形的代碼如下:

5)項目設置

在“Project”菜單中選擇“Settings”,加入OpenGL的兩個函數庫,即OpenGL32.lib和glu32.lib。 10.2基于OpenGL的基本圖形繪制

在OpenGL中,最基本的圖形是點,又稱頂點(Vertex),任何其他的圖形都是由頂點的集合來描述的,頂點間是否或怎樣連接是由繪制圖形的類型決定的。因此,在OpenGL中,所有的圖形都采用一系列有序的頂點來描述。需要指出的是,OpenGL所定義的點、線、多邊形等圖元與一般數學定義不一樣,存在一定的差別。一種差別源于基于計算機計算的限制。由于OpenGL中浮點計算精度有限,故點、線、多邊形的坐標值存在一定的誤差。另一種差別源于位圖顯示的限制,以這種方式顯示圖形,最小的顯示圖元是一個像素,盡管每個像素很小,但它們仍然比數學上所定義的點或線寬要大得多。當用OpenGL進行計算時,雖然是用一系列浮點數定義點,但每個點仍然是用單個像素顯示,只是近似擬合。

10.2.1點

OpenGL中,點稱為頂點,是一個n維向量,n=2,3,4。在缺省狀態(tài)下,點為一個像素。所有頂點在OpenGL內部計算時都使用三維坐標(x,y,z)來處理,用二維坐標(x,y)定義的點在OpenGL中默認z值為0。例如glVertex(2.0,1.0),定義了一個坐標為(2.0,1.0,0)的點。OpenGL定義點的函數為

glVertex{2,3,4}{sifd}(v)(TYPEcords)其中cords為用一個數組或坐標表示的頂點坐標,也可以是齊次坐標。例如:

glVertex2f(1.5,3.8);

glVertex3d(5.4,21.5,16.2);

glVertex2i(20,30);

glVertex3sv(coNstGLshortp)

/*p為一個點的數組*/要想在顯示器上顯示一點,必須用函數glBegin()通知OpenGL畫圖的類型,例如:

glBegin(GL_POINTS);

glVertex2f(1.5,3.8);

glVertex3d(5.4,21.5,16.2);

glVertex2i(20,30);

glEnd();

glBegin函數中的參數GL_POINTS是通知OpenGL下面的點要解釋成點并在顯示器上顯示點。

OpenGL還提供了控制點大小的函數glPointsize(),默認為一個像素,函數形式是:

voidglPointsize(glfloatsize)10.2.2線

在OpenGL中,繪制一條直線是通過定義兩個頂點來完成的,在定義頂點之前,應告訴OpenGL對應兩個頂點畫直線的動作。例如要畫一條直線,兩個端點是(30,30)和

(100,200),利用OpenGL的代碼段為:

glBegin(GL_LINES);

glVertex2f(30,30);

glVertex2f(100,200);

glEnd();如有多個頂點,則表示要畫的是折線。glBegin函數的參數應改為GL_LINE_STRIP,例如:

glBegin(GL_LINE_STRIP);

glVertex2f(30,30);

glVertex2f(80,30);

glVertex2f(40,60);

glVertex2f(70,50);

glEnd(

如果glBegin的參數是GL_LINE_LOOP,則畫出來的是封閉的多邊形。

用OpenGL的線型屬性定義函數,可以畫出直線的線型模式,函數為:

voidglLineStipple(Glintfactor,Glushortpattern);此命令有pattern和factor兩個參數。pattern是畫線操作時的一個模板,是一個0和1的二進制序列,在這個序列中每一位能影響一個像素,1表示畫點,0表示不畫點。例如pattern=0x3E03,化為二進制是0011111000000011,意味著繪制該線型時,先畫3個像素,然后空7個像素,再畫5個像素,空2個像素。如果啟動線型操作,線上的點由pattern決定是否繪制,即從pattern的最低位開始,逐個繪制線上的點,如果線還沒有畫完,線型的樣板已經用完,則將重復使用線型的樣板至完成畫線。參數factor是為了擴展線型,factor從1到255,表示pattern參數中所規(guī)定的像素的重復次數。當patten=2時,則參數pattern=0x3E03實際上表示的線型是00001111111111000000000000001111。具體的函數表示是:

glLineStipple(2,0x3E03);

結束時,調用glDisable(GL_LINE_STIPPLE)關閉。下面的代碼繪制了一個點線:啟動線型用glEnable(GL_LINE_STIPPLE)函數,關閉線型用glDisable(GL_LINE_STIPPLE)函數。

除了在OpenGL中可以定義線型外,還可以在畫線時使用函數glLineWidth來控制線的寬度。glLineWidth()函數形式如下:

glLineWidth(GLFloatwidth)

函數中的參數width指定要畫的線以像素計的近似寬度,在缺省情況下,width=1.0,此外要求width>0.0。

由于各圖形系統(tǒng)的具體性能是不一樣的,并不是所有線寬都支持,因此為了確保指定的線寬是可用的,可以通過下面的代碼獲得系統(tǒng)支持的線寬的范圍和它們之間的最小間隔:

Glfloatsizes[2];

Glfloatstep;

GLGetFloatv(GLLINEWIDTHRANGE,sizes);

GLGetFLoatv(gllinewidthgranularity,&step);

定義的sizes數組包含兩個元素,保存了glLineWidth的最小有效值和最大有效值;變量step保存了線寬之間允許的最小增量。

下面的程序給出了OpenGL的完整程序的框架實現,綜合演示了點的大小、線型和線寬的實現。10.2.3多邊形

OpenGL定義的多邊形是由一系列線段依次連接而成的封閉區(qū)域,多邊形可以是平面多邊形(即所有頂點在一個平面上),也可以是空間多邊形。OpenGL規(guī)定多邊形中的線段不能交叉,區(qū)域內不能有空洞,也即多邊形必須是凸多邊形(指多邊形任意非相鄰的兩點的連線位于多邊形的內部),不能是凹多邊形,否則不能被OpenGL函數接受。這些限制是為特別需要設定的。首先所有的多邊形都可以分割為多個凸多邊形。限制多邊形的類型容易實現硬件加速。在OpenGL中,多邊形的繪制也是由函數glBegin()和glEnd()來完成的。glBegin()函數的參數是GL_TRIANGLES。最簡單的多邊形是三角形,它只有三條邊。在實際應用中,往往需要繪制一些凹多邊形,通常解決的辦法是對它們進行分割,用多個三角形來替代。顯然,繪制這些三角形時,有些邊不應該繪制,否則,多邊形內部就會出現多余的線框。OpenGL提供的解決辦法是通過設置邊標志命令glEdgeFlag()來控制某些邊是否繪制,這個命令如下:

voidglEdgeFlag(GLbooleanflag);

voidglEdgeFlag(PGLbooleanpflag);

多邊形有多種繪制模式,如全填充式、輪廓點式、輪廓線式、圖案填充式及指定正反面等。下面分別介紹相應的OpenGL函數形式。

(1)多邊形模式設置。其函數為:

voidglPolygonMode(GLenumface,GLenummode);

參數face為GL_FRONT、GL_BACK或GL_FRONT_AND_BACK;參數mode為GL_POINT、GL_LINE或GL_FILL,分別表示繪制輪廓點式多邊形、輪廓線式多邊形或全填充式多邊形。在OpenGL中,多邊形分為正面和反面,對這兩個面都可以進行操作。在缺省狀況下,OpenGL對多邊形正反面是以相同的方式繪制的,要改變繪制狀態(tài),必須調用PolygonMode()函數。

(2)設置圖案填充式多邊形。其函數為:

voidglPolygonStipple(constGLubyte*mask);

參數mask是一個指向32x32位圖的指針。與線型繪制的道理一樣,二進制位為1時繪制,為0時不繪。注意,在調用這個函數前,必須先啟動glEnable(GL_POLYGON_STIPPLE);不用時用glDisable(GL_POLYGON_STIPPLE)關閉。

下面為一個多邊形擴展繪制實例: 10.3基于VC++的OpenGL坐標變換

OpenGL通過相機模擬,可以實現計算機圖形學中最基本的三維變換,即幾何變換、投影變換、裁剪變換、視圖變換等;同時,OpenGL還實現了矩陣堆棧等。理解、掌握了有關坐標變換的內容,即可真正走進精彩的三維世界。

10.3.1

OpenGL中三維物體的顯示

1.坐標系統(tǒng)

在現實世界中,所有的物體都具有三維特征,但計算機本身只能處理數字,故只能顯示二維的圖形。將三維物體及二維數據聯(lián)系在一起的唯一紐帶就是坐標。為了使被顯示的三維物體數字化,要在被顯示的物體所在的空間中定義一個坐標系。這個坐標系的長度單位和坐標軸的方向要適合對被顯示物體的描述,這個坐標系被稱為世界坐標系。世界坐標系是始終固定不變的。

OpenGL還定義了局部坐標系的概念。所謂局部坐標系,也就是坐標系以物體的中心為坐標原點,物體的旋轉或平移等操作都是圍繞局部坐標系進行的,這時,當物體模型進行旋轉或平移等操作時,局部坐標系也執(zhí)行相應的旋轉或平移操作。需要注意的是,如果對物體模型進行縮放操作,則局部坐標系也要進行相應的縮放。如果縮放比例在各坐標軸上不同,那么再經過旋轉操作后,局部坐標軸之間可能不再相互垂直。無論是在世界坐標系中進行轉換還是在局部坐標系中進行轉換,程序代碼都是相同的,只是不同的坐標系考慮的轉換方式不同罷了。

計算機對數字化的顯示物體做了加工處理后,要在圖形顯示器上顯示,就必須在圖形顯示器屏幕上定義一個二維直角坐標系,這個坐標系被稱為屏幕坐標系。這個坐標系坐標軸的方向通常取成平行于屏幕的邊緣,坐標原點取在左下角,長度單位常取成一個像素。

2.三維物體的相機模擬

為了說明在三維物體到二維圖像之間需要經過什么樣的變換,我們引入了相機(Camera)模擬的方式。假定用相機來拍攝這個世界,那么在相機的取景器中,就存在人眼和現實世界之間的一個變換過程,如圖10-4所示。

從三維物體到二維圖像,就如同用相機拍照一樣,通常都要經歷以下幾個步驟:

(1)將相機置于三角架上,讓它對準三維景物,這相當于OpenGL中調整視點的位置,即視點變換(ViewingTransformation)。

(2)將三維物體放在場景中的適當位置,這相當于OpenGL中的模型變換(ModelingTransformation),即對模型進行旋轉、平移和縮放。圖10-4相機模擬OpenGL中的各種坐標變換

(3)選擇相機鏡頭并調焦拍照,使三維物體投影在二維膠片上,這相當于OpenGL中把三維模型投影到二維屏幕上的過程,即OpenGL中的投影變換(ProjectionTransformation)。

OpenGL中投影的方法有兩種,即正投影和透視投影。為了使顯示的物體能以合適的位置、大小和方向顯示出來,必須要通過投影。有時為了突出圖形的一部分,只把圖形的某一部分顯示出來,這時可以定義一個三維視景體(ViewingVolume)。正投影時一般是一個長方體的視景體,透視投影時一般是一個如棱臺似的視景體。只有視景體內的物體能被投影在顯示平面上,其他部分則不能。

(4)沖洗照片,決定二維相片的大小,這相當于OpenGL中的視圖變換(ViewportTransformation)。在屏幕窗口內可以定義一個矩形,稱為視圖(Viewport),物體投影后的圖形就在視圖內顯示。視圖變換規(guī)定了屏幕上顯示場景的范圍和尺寸。

通過上面幾個步驟,一個三維空間里的物體就可以用相應的二維平面物體表示了,也就能在二維的電腦屏幕上正確顯示了??偟膩碚f,三維物體的顯示過程如圖10-5所示。圖10-5三維物體的顯示過程10.3.2

OpenGL中的幾種變換

OpenGL中的各種轉換是通過矩陣運算實現的,具體地說,就是當發(fā)出一個轉換命令時,該命令會生成一個4×4階的轉換矩陣(OpenGL中的物體坐標一律采用齊次坐標,即(x,y,z,w),故所有變換矩陣都采用4×4矩陣),當前矩陣與這個轉換矩陣相乘,從而生成新的當前矩陣。例如,對于頂點坐標v,轉換命令通常在頂點坐標命令之前發(fā)出,若

當前矩陣為C,轉換命令構成的矩陣為M,則發(fā)出轉換命令后,生成的新的當前矩陣為CM,這個矩陣再乘以頂點坐標v,從而構成新的頂點坐標CMv。上述過程說明,程序中繪制頂點前的最后一個變換命令最先作用于頂點之上。這同時也說明,在OpenGL編程中,實際的變換順序與指定的順序是相反的。

1.視點變換

視點變換確定了場景中物體的視點位置和方向,就如上邊提到的,它像是在場景中放置了一架照相機,讓相機對準要拍攝的物體。缺省時,相機(即視點)定位在坐標系的原點(相機初始方向都指向z軸的負方向),它同物體模型的缺省位置是一致的,顯然,如果不進行視點變換,則相機和物體是重疊在一起的。執(zhí)行視點變換的命令和執(zhí)行模型變換的命令是相同的。在用相機拍攝物體時,我們可以保持物體的位置不動,而將相機移離物體,這就相當于視點變換;另外,我們也可以保持相機的固定位置,將物體移離相機,這就相當于模型變換。這樣,在OpenGL中,以逆時針旋轉物體就相當于以順時針旋轉相機。因此,我們必須把視點變換和模型變換結合在一起考慮,而對這兩種變換單獨進行考慮是毫無意義的。除了用模型變換命令執(zhí)行視點變換之外,OpenGL實用庫還提供了gluLookAt()函數,該函數有三個變量,分別定義了視點的位置、相機瞄準方向的參考點以及相機的向上方向。該函數的原型為:

voidgluLookAt(GLdoubleeyex,GLdoubleeyey,GLdoubleeyez,GLdoublecenterx,GLdoublecentery,GLdoublecenterz,GLdoubleupx,GLdoubleupy,GLdoubleupz);該函數定義了視點矩陣,并用該矩陣乘以當前矩陣。eyex、eyey、eyez變量定義了視點的位置;centerx、centery、centerz變量指定了參考點的位置,該點通常為相機所瞄準的場景中心軸線上的點;upx、upy、upz變量指定了向上向量的方向。

通常,視點變換操作在模型變換操作之前發(fā)出,以便模型變換先對物體發(fā)生作用。場景中物體的頂點經過模型變換之后移動到所希望的位置,然后再對場景進行視點定位等操

作。模型變換和視點變換共同構成模型視景矩陣。

2.模型變換

模型變換是在世界坐標系中進行的。缺省時,物體模型的中心定位在坐標系的中心處。OpenGL在這個坐標系中有三個命令,可以進行模型變換。

(1)glTranslate{fd}(TYPEx,TYPEy,TYPEz);

該函數用指定的x、y、z值沿著x軸、y軸、z軸平移物體(或按照相同的量值移動局部坐標系)。

(2)glRotate{fd}(TYPEangle,TYPEx,TYPEy,TYPEz);

該函數中第一個變量angle指定模型旋轉的角度,單位為度(°);后三個變量表示以原點(0,0,0)到點(x,y,z)的連線為軸線逆時針旋轉物體。例如,glRotatef(45.0,0.0,0.0,1.0)的結果是繞z軸旋轉45°。

(3)glScale{fd}(TYPEx,TYPEy,TYPEz);

該函數可以對物體沿著x、y、z軸分別進行放大縮小。函數中的三個參數分別是x、y、z軸方向的比例變換因子。缺省時都為1.0,即物體沒有變化。程序中物體y軸比例為2.0,其余都為1.0,即將立方體變成長方體。

3.投影變換

經過模型視景的轉換后,場景中的物體放在了所希望的位置上,但由于顯示器只能用二維圖像顯示三維物體,因此就要靠投影來降低維數(投影變換類似于選擇相機的鏡頭)。

事實上,投影變換的目的就是定義一個視景體,使得視景體外多余的部分被裁剪掉,最終進入圖像的只是視景體內的有關部分。投影包括透視投影(PerspectiveProjection)和正視投影(OrthographicProjection)兩種。

1)透視投影

透視投影符合人們的心理習慣,即離視點近的物體大,離視點遠的物體小,遠到極點即為消失,成為滅點。它的視景體類似于一個頂部和底部都被切割過的棱椎,也就是棱臺透視投影通常用于動畫、視覺仿真以及其他許多具有真實性反映的方面。

OpenGL透視投影函數有以下兩個:

(1)voidglFrustum(GLdoubleleft,GLdoubleright,GLdoublebottom,GLdoubletop,GLdoublenear,GLdoublefar);

它創(chuàng)建一個透視視景體。其操作是創(chuàng)建一個透視投影矩陣,并且用這個矩陣乘以當前矩陣。這個函數的參數只定義近裁剪平面的左下角點和右上角點的三維空間坐標,即(left,bottom,-near)和(right,top,-near);最后一個參數far是遠裁剪平面的z負值,其左下角點和右上角點空間坐標由函數根據透視投影原理自動生成。near和far表示離視點的

遠近,它們總為正值。該函數形成的視景體如圖10-6所示。圖10-6函數glFrustum()形成的視景體

(2)voidgluPerspective(GLdoublefovy,GLdoubleaspect,GLdoublezNear,GLdoublezFar);

它也創(chuàng)建一個對稱透視視景體,但它的參數定義與函數glFrustum()的不同:參數fovy定義視野在x-z平面的角度,范圍是[0.0,180.0];參數aspect是投影平面寬度與高度的比率;參數zNear和zFar分別是近、遠裁剪面沿z負軸到視點的距離,它們總為正值。該函數形成的視景體如圖10-7所示。圖10-7函數gluPerspective()形成的視景體以上兩個函數缺省時,視點都在原點,視線沿z軸指向負方向。

2)正視投影

正視投影簡稱正投影,又叫平行投影。這種投影的視景體是一個矩形的平行管道,也就是一個長方體,如圖10-8所示。正投影的最大一個特點是無論物體距離相機多么遠,投影后的物體大小尺寸都不變。這種投影通常用在建筑藍圖繪制和計算機輔助設計等方面,這些行業(yè)要求投影后的物體尺寸及相互間的角度不變,以便施工或制造時物體比例大小正確。圖10-8正投影

OpenGL正投影函數有以下兩個:

(1)voidglOrtho(GLdoubleleft,GLdoubleright,GLdoublebottom,GLdoubletop,GLdoublenear,GLdoublefar);

它創(chuàng)建一個平行視景體。實際上這個函數的操作是創(chuàng)建一個正投影矩陣,并且用這個矩陣乘以當前矩陣。其中近裁剪平面是一個矩形,矩形左下角點三維空間坐標是(left,bottom,-near),右上角點是(right,top,-near);遠裁剪平面也是一個矩形,左下角點空間坐標是(left,bottom,-far),右上角點是(right,top,-far)。所有的near和far值同時為正或同時為負。如果沒有其他變換,正投影的方向平行于z軸,且視點朝向z負軸。這意味著物體在視點前面時far和near都為負值,物體在視點后面時far和near都為正值。

(2)voidgluOrtho2D(GLdoubleleft,GLdoubleright,GLdoublebottom,GLdoubletop);

它是一個特殊的正投影函數,主要用于二維圖像到二維屏幕上的投影。它的near和far缺省值分別為-1.0和1.0,所有二維物體的z坐標都為0.0。因此它的裁剪面是一個左下角點為(left,bottom)、右上角點為(right,top)的矩形。

4.視圖變換

視圖變換就是將視景體內投影的物體顯示在二維的視圖平面上。運用相機模擬方式,我們很容易理解視圖變換類似于照片的放大與縮小。在計算機圖形學中,它的定義是將經過幾何變換、投影變換和裁剪變換后的物體顯示于屏幕窗口內指定的區(qū)域內,這個區(qū)域通常為矩形,稱為視圖。

OpenGL中的相關函數是:

glViewport(GLintx,GLinty,GLsizeiwidth,GLsizeiheight);這個函數定義一個視圖。函數參數(x,y)是視圖在屏幕窗口坐標系中的左下角點坐標,參數width和height分別是視圖的寬度和高度。缺省時,參數值即(0,0,winWidth,winHeight)指的是屏幕窗口的實際尺寸大小。所有這些值都是以像素為單位,全為整型數。

5.裁剪變換

在OpenGL中,除了視景體定義的六個裁剪平面(上、下、左、右、前、后)外,用戶還可自己再定義一個或多個附加裁剪平面,以去掉場景中無關的目標,如圖10-9所示。圖10-9附加裁剪平面附加平面裁剪函數為:

voidglClipPlane(GLenumplane,ConstGLdouble*equation);

函數參數equation指向一個擁有四個系數值的數組,這四個系數分別是裁剪平面Ax+By+Cz+D=0的A、B、C、D值。因此,由這四個系數就能確定一個裁剪平面。參數plane是GL_CLIP_PLANEi(i=0,1,…),用于指定裁剪面號。

在調用附加裁剪函數之前,必須先啟動glEnable(GL_CLIP_PLANEi),使得當前所定義的裁剪平面有效;當不再調用某個附加裁剪平面時,可用glDisable(GL_CLIP_PLANEi)關閉相應的附加裁剪功能。

下面這個例子不僅說明了附加裁剪函數的用法,而且調用了gluPerspective()透視投影函數,其中的用法讀者可以細細體會。例程如下:

6.矩陣棧的操作

在講述矩陣棧之前,首先介紹兩個基本OpenGL矩陣操作函數。

(1)voidglLoadMatrix{fd}(constTYPE*m);

它設置當前矩陣中的元素值。函數參數*m是一個指向16個元素(m0,m1,…,m15)的指針,這16個元素就是當前矩陣M中的元素,其排列方式如下:

(2)voidglMultMatrix{fd}(constTYPE*m);

它用當前矩陣去乘*m所指定的矩陣,并將結果存放于*m中。當前矩陣可以是用glLoadMatrix()指定的矩陣,也可以是其他矩陣變換函數的綜合結果。

OpenGL的矩陣堆棧指的就是內存中專門用來存放矩陣數據的某塊特殊區(qū)域。一般說來,矩陣堆棧常用于構造具有繼承性的模型,即由一些簡單目標構成的復雜模型。矩陣堆棧對復雜模型運動過程中的多個變換操作之間的聯(lián)系與獨立十分有利。因為所有矩陣操作函數如glLoadMatrix()、glMultMatrix()、glLoadIdentity()等只處理當前矩陣或堆棧頂部矩陣,這樣堆棧中下面的其他矩陣就不受影響。堆棧操作函數有以下兩個:

(1)voidglPushMatrix(void);

該函數表示將所有矩陣依次壓入堆棧中,頂部矩陣是第二個矩陣的備份;壓入的矩陣數不能太多,否則會出錯。

(2)voidglPopMatrix(void);

該函數表示彈出堆棧頂部的矩陣,令原第二個矩陣成為頂部矩陣,接受當前操作,故原頂部矩陣被破壞;當堆棧中僅存一個矩陣時,不能進行彈出操作,否則會出錯。 10.4用OpenGL生成曲線和曲面

10.4.1樣條曲線的繪制

1.定義求值器

在OpenGL中,為了繪制一條樣條曲線,必須先定義求值器,然后才能計算曲線上點的坐標并完成曲線的繪制。求值器(Evaluator)是利用Bernstein多項式進行工作的一般機制,可以應用任意次數的多項式,可以處理一到四維的情形,可以自動生成法向和紋理坐標,在GLU中支持NURBS二次曲面。求值程序是OpenGL中用控制點來描述曲線或曲面上的點的工具。利用求值程序,可以繪制出由控制點所定義的曲線曲面。對于樣條曲線,OpenGL使用一維基函數,并且只使用如下形式的多項式:

上述多項式是n次Bezier多項式。設Pi是控制點,則Bezier曲線為

這樣,C(u)就是樣條曲線的求值器。u的取值范圍為[0,1]。如果u的取值范圍為[U1,U2],則求值器為

2.一維求值器函數glMap1()

OpenGL求值器是以Bezier曲線曲面為基礎來繪制樣條曲線或曲面的。定義一維求值器的函數是glMap1(),該函數對應于Bezier曲線方程。

函數的原型如下:

VoidglMap1{fd}(GLenumtarget,TYPEu1,TYPEu2,Glintstride,Glintorder,constTYPE*points);

參數說明:

target:指定控制點所描述的內容。其可取的值及意義如表10-1所示。表10-1

target的取值及含義

u1,u2:限定參數u的變化范圍,并把它提供給函數glEvalCoord1()。

stride:指定控制點之間的浮點數或雙精度數的個數。

order:等于次數加1,與控制點數目一致,必須是正整數。

points:指向控制點數組的指針,指向第一個控制點的第一個坐標。

在調用該函數之前,還需要用表10-1中的參數值來激活求值器程序。只需以target的值作為映射名調用glEnable(映射名)和gldisable(映射名)函數,即可激活或者取消求值器程序。

3.計算曲線坐標

計算曲線坐標的函數是glEvalCoord1(),函數的原型如下:

voidglEvalCoord1{fd}(TAPEu);

功能:對已定義并激活的一維的求值器程序進行計算,得到Bezier曲線上點的坐標值。

參數說明:

u:指定沿著曲線進行計算的u參數值。

該函數每調用一次只產生一個頂點的坐標值。這里的坐標是廣義的,既可以是物體的頂點坐標,也可以是顏色、法線或紋理坐標。

4.計算均勻間隔坐標

在通常情況下,計算曲線坐標時,采用均勻分割定義域的方法。OpenGL提供了兩個函數:glMapGrid1()和glEvalMesh1()。

函數glMapGrid1()的原型如下:

voidglMapGrid1{fd}(GLintun,TAPEu1,TAPEu2);

功能:定義一個一維的網格。

參數說明:

un:指定網格范圍[u1,u2]之間的等份數,必須是正整數。u1、u2指定整型網格域值,取值范圍是i=0到i=un。函數glEvalMesh1()的原型如下:

voidglEvalMesh1{fd}(GLenummode,GLinti1,GLinti2);

功能:計算點或線的一維網格。

參數說明:

mode:指定是計算點還是線的一維網格,可取的符號常量是GL_POINT和GL_LINE。

i1,i2指定網格區(qū)域變量i的第一個和最后一個整數值。

這兩個函數的使用方法是首先調用glMapGrid1()定義一個一維網格,然后調用glEvalMesh1()計算相應的坐標值。函數glEvalMesh1()穿過一個一維網格的整數區(qū)域,其范圍是函數glMap1()所指定的求值影射的區(qū)域。參數mode決定所得的頂點是由孤立的點繪制還是連成線。5.編程實例10.4.2樣條曲面的繪制

樣條曲面的繪制方法在原理上與樣條曲線基本相同,所不同的是曲面使用二維求值器,并且控制點連接起來形成一個網格。

1.定義二維求值器

對于曲面,求值器函數使用兩個參數u、v,使用如下形式的多項式:其中,Pij是m×n個控制點,基函數和與一維求值器基函數相同。二維求值器函數即對應于Bezier曲面方程:

voidglMap2{fd}(GLenumtarget,TYPEu1,TYPEu2,Glintustride,GLintuorder,TYPEv1,TYPEv2,GLintvstride,GLintvorder,constTYPE*points);

功能:定義二維求值器程序,即Bezier曲面方程。

參數說明:

target:可以使用表5.1中的任何值,只需將MAP1改為MAP2。

u1,u2:限定參數u的變化范圍。u1,u2的初始值是0,1。

v1,v2:限定參數v的變化范圍。v1,v2的初始值是0,1。

ustride,vstride:指定控制點之間的浮點數或雙精度數的個數。

uorder,vorder:指定在u方向和v方向的控制點個數。

*points:指向控制點的指針。

定義了求值函數之后,即可對其進行計算,以根據給定參數值得到曲線曲面上的點,從而繪制出相應的Bezier曲線曲面。

2.計算曲面坐標

計算曲面坐標的函數是glEvalCoord2(),函數的原型如下:

voidglEvalCoord2{fd}[v](TAPEu,TAPEv);

功能:求取有效的二維映射值。

參數說明:

u,v:指定已經由函數glMap2定義的基礎函數的域坐標u和v的值。

該函數計算曲面上頂點的坐標值。這里的坐標也是廣義的,既可以是物體的頂點坐標,也可以是顏色、法線或紋理坐標。

3.計算均勻曲面坐標

與一維的情況相同,OpenGL提供了兩個函數glMapGrid2()和glEvalMesh2()計算曲面坐標,函數原型如下:

voidglMapGrid2{fd}(GLintun,TAPEu1,TAPEu2,GLintvn,TAPEv1,TAPEv2);

voidglEvalMesh2{fd}(GLenummode,GLinti1,GLinti2,GLintj1,GLintj2);

功能:

定義和計算二維網格的坐標值。參數說明:

un,vn:指定網格范圍[u1,u2]和[v1,v2]之間的等份數,必須是正整數。u1,u2指定整型網格域值,取值范圍是i=0到i=un。v1,v2指定整型網格域值,取值范圍是j=0到j=vn。

mode:指定是計算點、線還是多邊形的二維網格??扇〉姆柍A渴?/p>

GL_POINT,GL_LINE和GL_FILL。

i1,i2:指定網格區(qū)域變量i的第一個和最后一個整數值。

j1,j2:指定網格區(qū)域變量j的第一個和最后一個整數值。4.編程實例

OpenGL的實用函數庫(GLU)提供了另一種曲線、曲面繪圖接口,即NURBS接口。這一接口同樣是建立在求值器的基礎上的,但更靈活,使用起來也更方便。 10.5

OpenGL的光照處理

從上述可見,要顯示一張簡單的曲面所涉及的內容和計算是相當復雜的,OpenGL把相當復雜的工作集成在相應的

函數中,只需對參數進行處理便可得到需要的光照模型。下面就介紹如何使用OpenGL進行光照處理。

10.5.1光源的定義

光源有許多特性,如顏色、位置、方向等。不同特性的光源,作用在物體上的效果是不一樣的。定義一個光源的主要工作就是定義它的各種特性,OpenGL通過光源特性的函數glLight*()來定義光源。

voidglLight{if}(GLenumlight,GLenumpname,TYPE*param);

voidglLight{if}v(GLenumlight,GLenumpname,TYPE*param);

此函數定義光源的某特性。其中,light指定光源編號,在一個場景最多定義八個不同的光源,編號為GL-LIGHT0,GL-LIGHT1,…,GL-LIGHT7;參數pname指定光源特性的名稱,即是什么種類的光,其取值見表10-2;參數param為指向param所指屬性值的指針,它可以指向一個數值,也可以指向一個值,具體由所定義的屬性而定。表10-2

pname參數的取值及意義下面是定義編號為GL_LIGHT光源的例子:

GLfloatlight_ambient[]={0.0,0.0,0.0,1.0};

GLfloatlight_diffuse[]={1.0,1.0,1.0,1.0};

GLfloatlight_specular[]={1.0,1.0,1.0,1.0};

GLfloatlight_position[]={1.0,1.0,1.0,1.0};

glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);

glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);

glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);

glLightfv(GL_LIGHT0,GL_POSITION,light_position);

光源的特性定義后這個光源是否打開是要說明的,用glenable(光源號)打開光源,否則光源對場景中的物體光照不起作用。

1.顏色

在glLight()參數pname取值為GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR時指定光源中相應組成部分的顏色強度。

GL_AMBIENT指定環(huán)境光的RGBA強度,當其特性值為{0.0,0.0,0.0,1.0}時,表示沒有環(huán)境光,這是默認狀態(tài)。

GL_DIFFUSE指定漫反射光的RGBA強度,默認情況下對于GL_LIGHT0、GL_DIFFUSE特性值為{1.0,1.0,1.0,1.0},對于其他編號為GL_LIGHT1,…,LIGHT7的光源,該特性值為{0.0,0.0,0.0,0.0},此特性可以視為光源的顏色。

GL_SPECULAR用于指定鏡面反射的RGBA強度,默認時,對于GL_LIGHT0該特性值為{1.0,1.0,1.0,1.0},對于其他光源,該特性值為{0.0,0.0,0.0,0.0}。

2.位置

使用GL_POSITION定義光源位置坐標(x,y,z,w)。當w=0時,表示定義的位置在無窮遠,而(x,y,z)僅說明光的方向,此時叫方向光源。當ω≠0時,則定義一個較近的光源,(x,y,z)表示光源的坐標。例如:

Glfloatlight_position[]={1.0,1.0,1.0,1.0};

//定義了一個方向光源

glLightfv(GL_LIGHT0,GL_POSITION,light_position);

3.衰減

光線強度隨光源距離的增加而減弱,若光源是無限遠,則光線強度不衰減。對于一般的位置光源,OpenGL使用下面的衰減因子來衰減光線的強度:

其中:d為光源位置到物體頂點的距離;kc為GL_CONSTANT_ATTENUATION,默認值為1.0;ke為GL_LINER_ATTENUATION,默認值為0.0;kg為GL_QUADRATIC_ATTENUATION,默認值為0.0。

4.聚光

一般情況下,光源光線是向四周發(fā)射,可以使用GL_DOT_CUTDFF來限制光線的范圍,缺省是180°。當然,除了指定光發(fā)散角度外,還需指定聚光狀態(tài)下的方向。例如:

glLlightf(GL_LIGHT0,GLSPOT_CUTOFF,45.0);

//45°角范圍

GLfloatspot_direction[]={-1.0,-1.0,0.0};

glLightfv(GL_LIGHTO,GL_SPOT_DIRECTION,spot_direction)10.5.2材質的定義

OpenGL用材質來描述物體表面特性,通過指定物體表面對光的反射率來確定物體的顏色。設置材質屬性的函數是:

voidglMaterial{if}(GLenumface,GLenumpname,TYPEparam);

其中,參數face是GL_FRONT、GL_BACK或GL_FRONT_AND_BACK指定當前材質作用物體的哪一面;參數pname設置材質的屬性,其取值見表10-3。表10-3

pname的取值及意義例如,將當前材質的散射和環(huán)境反射率設置為(0.1,0.5,0.8,1.0):

GLfloatmat_amb_diff[]={0.1,0.5,0.8,1.0}

glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_amb_diff)

10.5.3

OpenGL的光照實例

下面的程序實現了球面的光照效果。球體的光照效果如圖10-10所示。圖10-10

OpenGL畫出的光線照射曲面 10.6

OpenGL對交互繪圖的支持

OpenGL提供了一些機制,通過它們可實現多種交互技術。本節(jié)僅介紹OpenGL對選擇、反饋和橡皮筋技術的支持與實現。OpenGL提供了一種簡單直觀的選擇機制,來實現圖形元素的拾??;反饋機制(Select&Feedback)用來滿足用戶使用鼠標交互操作圖形的需要;利用OpenGL的雙緩存機制可方便地實現橡皮筋功能。

10.6.1使用OpenGL的選擇機制實現拾取功能

使用OpenGL選擇機制的操作步驟為:設置選擇緩沖區(qū)→進入選擇模式→創(chuàng)建名字?!O置拾取矩陣→繪制圖元→切換回渲染模式→確定拾取對象。

1.設置選擇緩沖區(qū)

在進入選擇模式之前,需調用glSelectBuffer()為返回的選擇信息設置緩沖區(qū),以便最后能通過分析選擇緩沖中的數據來確定被選中圖元。

glSelectBuffer()的原型如下:

voidglSelectBuffer(GLsizeisize,GLuint*buffer);

其中,參數*buffer是指向無符號整數數組的指針,該數組就是所設置的用于存儲返回選擇數據的緩沖區(qū);參數size說明數組中最多能夠保存的值的個數。

2.進入選擇模式

OpenGL的繪圖模式有渲染模式、選擇模式和反饋模式,其中渲染模式為默認工作模式。若想使用選擇機制,則必須設置當前繪圖模式為選擇模式。

模式設置函數GLintglRenderMode(GLenummode);能控制應用程序進入的模式。參數mode的取值可以是GL_RENDER(渲染模式)、GL_SELECT(選擇模式)或GL_FEEDBACK(反饋模式),分別指定相應模式。

一旦設置為某種模式,應用程序將保持處于給定模式,直到再次以不同的參數調用glRenderMode()為止。

3.創(chuàng)建名字棧

名字棧是返回選擇信息的基礎,其中存放一系列圖元的標識(整數),每當發(fā)布繪制命令時便將此圖元的標識壓入名字棧。經計算后,若圖元被選中,則名字棧中此圖元的標識便會返回到選擇緩沖區(qū)。然后通過提取選擇緩沖中的名字棧的內容,便可得到有關被選中圖元的信息。

在使用名字堆棧之前,需要建立名字棧。用glInitNames()創(chuàng)建并初始化(簡單地清空)名字棧。名字棧的控制命令有三個:glPushName()將圖元名字壓入棧,glPopName()從棧中彈出名字,glLoadName()替換棧頂的名字。

glPushName()的原型為voidglPushName(GLuintname);,它將name壓入名字棧。壓入名字超過棧容量時將生成一個GL_STACK_OVERFLOW錯誤。名字棧深度因OpenGL實現不同而不同,但最少也能容納64個名字??梢杂脜礕L_NAME_STACK_DEPTH調用glGetIntegerv()以獲取名字棧的深度。

glPopName()的原型為voidglPopName(void);,它彈出名字棧的棧頂名字。從空棧中彈出名字會引發(fā)GL_STACK_UNDERFLOW錯誤。

glLoadName()的原型為voidglLoadName(GLuintname);,實現用name取代名字棧棧頂的那個名字。如果棧是空的,比如剛調用過glInitName()后就是這樣,glLoadName()生成一個GL_INVALID_OPRATION錯。為避免這些出錯情況,如果棧初始時是空的,那么在調用glPopName()和glLoadName()之前至少要調用一次glPushName()以在名字棧中放進一個名字。

4.設置拾取矩陣

要想使OpenGL能夠正確判斷哪個圖元被選中,還要設置合適的投影變換矩陣和模型視圖矩陣,使得在選擇模式下的繪圖代碼能夠與繪圖模式下的相吻合。要想讓OpenGL判斷哪個圖元被選中,則必須提供一個拾取位置信息,通常是鼠標的位置。所以,此處還要設置拾取矩陣,用于保存拾取位置信息。

設置拾取矩陣

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論