用過opengl的人,應該都知道,opengl是自帶拾取功能的,但用過的人應該也知道,這功能確實不好用。
opengl自帶的選擇功能主要有兩種,名字堆疊(拾取)和讀深度值判斷選擇,但這兩種方法在實際專案中,未必都好用。
方法一:名字堆疊的方法,需要切換渲染模式,操作命名堆疊,計算揀選矩陣,檢查選中記錄。當要渲染的資料量特別大或渲染的物件眾多時,顯然是不可取的。
方法二:glreadpixel方法,讀深度值的方法,這種方法比前面一種方法在某些時候稍微好用些,但有乙個致命的限制,你滑鼠選擇的時候,必須選擇到繪有實體的地方,否則就得不到正確的深度值。例如你渲染乙個三維地形圖,地形以tin的方式渲染,如果你想選擇某個頂點,但滑鼠落在空白區,你就無法得到正確的深度值,得不到正確的深度值,自然沒法根據gluunproject函式反算到真實的地形座標點,而實際應用中應該是即使你沒完全落在該頂點上,也應該可以根據乙個緩衝,在所有緩衝區內部的點集中選擇乙個距離游標最近的點作為你選擇的點。
本文介紹一種方法——射線選擇,這種方法也是遊戲界和三維地形程式設計普遍採用的選擇方法。
首先介紹乙個二維三維座標轉換函式:gluunproject()
此函式的具體用途是將乙個
opengl
視區內的二維點轉換為與其對應的場景中的三維座標。
轉換過程如下圖所示(由點
p在視窗中的
xy座標得到其在三維空間中的世界座標):
這個函式在
glu.h
中的原型定義如下:
**
int apientry gluunproject (
gldouble winx,
gldouble winy,
gldouble winz,
const gldouble modelmatrix[16],
const gldouble projmatrix[16],
const glint viewport[4],
gldouble *objx,
gldouble *objy,
gldouble *objz);
其中前三個值表示視窗座標,中間三個分別為模型檢視矩陣(
model/view matrix
),投影矩陣(
projection matrix
)和視區(
viewport
),最後三個為輸出的世界座標值。
第二步,首先獲得檢視矩陣,投影矩陣,視區三個陣列值。
**
** glint viewport[4];
gldouble modelview[16];
gldouble projection[16];
glgetintegerv(gl_viewport, viewport); // 得到的是最後乙個設定視口的引數
glgetdoublev(gl_modelview_matrix, modelview);
glgetdoublev(gl_projection_matrix, projection);
獲取這三個變數的**,應該放在繪製發生前,三個矩陣定以後。否則glpopmatrix之類的函式,可能導致你無法得到真正的投影矩陣和檢視矩陣。
第三步,獲取射線。因為兩點確定一條線,所以,先通過計算檢視最近點和最遠點,得到該射線。
**
winx = point.x;
winy = screenheight - point.y;
//獲取畫素對應的前裁剪面的點座標
bool bresult = gluunproject(winx, winy, 0.0, modelview, projection, viewport, &posx, &posy, &posz);
fpoint3 nearpoint;
nearpoint.x = posx; nearpoint.y = posy; nearpoint.z = posz;
//獲取畫素對應的後裁剪面的點座標
bresult = gluunproject(winx, winy, 1.0, modelview, projection, viewport, &posx, &posy, &posz);
fpoint3 farpoint;
farpoint.x = posx; farpoint.y = posy; farpoint.z = posz;
第四步,計算待選擇目標跟該的關係,將與射線距離最近的物件,作為選擇物件。
第五步,本文繪製了分布在不同三維空間的5個點,用滑鼠右鍵,可以進行點的選擇,如果選中,點會變成黃色,滑鼠左鍵可以隨意對這些點進行旋轉等。
程式源**
opengl實現X射線渲染
x射線也就是輪郭線 實現原理 物體表面的法線與入射光線的夾角為90度時,剛好能看到物體的輪郭線 實現效果,不同的計算方式會得到不同的效果 頂點shader attribute vec3 pos attribute vec2 texcoord attribute vec3 normal uniform...
用OpenGL實現射線揀取物件
本文 http bbs.gameres.com showthread.asp?postid 100771 關於用射線原理來揀取物件網上已經有完整的理論,另外directx也提供了乙個pick例子來演示,在這裡我將這些資料和理論來稍微的總結,並給出opengl下的完整實現。相關的理論大體來自一篇英文資...
opengl的選擇模式
步驟按順序來,不然會無法拾取,返回 1 1,初始化命名緩衝,glselectbuffer buffer size,buffer 2,設定渲染模式為gl select 3,初始化命名堆疊,glinitnames glpushname 0 示例 void select object cpoint poi...