opengl
中採用一種比較複雜的方式實現了拾取操作,即選擇模式。選擇模式是一種繪製模式,它基本思想是在一次拾取操作時,系統根據拾取操作的引數(如滑鼠位置)生成乙個特定視景體,然後由系統重新繪製場景中的所有圖元,但這些圖元並不會繪製到顏色快取中,系統跟蹤有哪些圖元繪製到了這個特定的視景體中,並將這些物件的識別符號儲存到拾取緩衝區陣列中。
在opengl
中實現拾取操作主要包括以下步驟。
1.設定拾取緩衝區
拾取時,在特定的視景體中繪製每個物件都會產生乙個命中訊息,命中訊息將存放在乙個名字堆疊中,這個名字堆疊就是拾取緩衝區。函式:
void glselectbuffer(glsizei n, glunint*buff);
指定了乙個具有
n個元素的整形陣列
buffer
作為拾取緩衝區。對於每個命中訊息,都會在拾取緩衝區陣列中新增一條記錄,每條記錄包含了以下的資訊:(1
)命中發生時堆疊中的名稱序號;(2
)拾取圖元所有頂點的最大和最小視窗
z座標。這兩個值的範圍都位於[0,
1]內,他們都乘以
232-1
,然後四捨五入為最接近的無符號整數。(3
)命中發生時堆疊中的內容,最下面的名稱排在最前面。
2.進入選擇模式
在定義了拾取緩衝區後,需要啟用選擇模式。選擇模式的指定採用函式:
glint glrendermode(glenum mode);
其中,引數
mode
值可以為
gl_render
(預設值)、
gl_select
或gl_feedback
,分別指定應用程式處於渲染模式、選擇模式和反饋模式。應用程式一直處於當前模式下,直到呼叫本函式改變為其他模式為止。
3.名字堆疊操作
在選擇模式下,需要對名字堆疊進行一系列操作,包括初始化、壓棧、彈棧以及棧頂元素操作等。
void glinitnames();//
初始化名字堆疊,其初始狀態為空
void glpushname(gluint name);//
將乙個名字壓入堆疊,其中
name
是標識圖元的乙個無符號整數值
void glload name(gluint name);//
將名字堆疊的棧頂元素替換為
name
void glpopname();//
將棧頂元素彈出
4.設定合適的變換過程
拾取操作可以通過矩形拾取視窗來實現,我們可以用下面的函式呼叫:
glupickmatrix(xpick, ypick, widthpick, heightpick,*vp);
其中引數
xpick
和ypick
指定相對於顯示區域左下角的拾取視窗中心的雙精度浮點螢幕座標值。當使用滑鼠進行選擇操作時,
xpick
和ypick
由滑鼠位置確定,但要注意
y座標的反轉。引數
widthpick
和heightpick
指定拾取視窗的雙精度浮點寬高值。引數
vp指定了乙個包含當前顯示區域的座標位置和尺寸等引數的整型陣列,該引數可以通過函式
glgetintegerv
來獲得。這個函式可以設定乙個用於拾取操作的觀察空間。
5.為每個圖元分配名字並繪製
為了標識圖元,在圖元繪製過程中需要用乙個整型值指定圖元的名稱,並在選擇模式下,將這個名字壓入到名字堆疊中。為了節省名字堆疊的空間,應該在圖元繪製完成後,將其名字從堆疊中彈出。
6.切換回渲染模式
在選擇模式下,所有的圖元繪製完成後,應該再次呼叫函式
glrendermode
選擇渲染模式,在幀緩衝儲存器中繪製圖元,並返回被選中圖元的個數。
7.分析選擇緩衝區中的資料
拾取操作完成之後,可以根據選擇緩衝區中的內容進行分析,以確定拾取的圖元。
程式3-3opengl
實現的拾取操作的例子
#include #include "stdio.h"
const glint picksize = 32;
int winwidth = 400, winheight = 300;
voidinitial(void)
voiddrawrect(glenum mode)
voidprocesspicks(glint npicks, gluint pickbuffer)
{ glint i;
gluint name, *ptr;
printf("選中的數目為%d個\n",npicks);
ptr=pickbuffer;
for(i=0;i
利用osgUtil進行拾取操作
今天遇到乙個奇怪的現象,在控制台中寫好的拾取 結果發現整合到qt中總是報錯 我就納悶了。找了一圈,網上都沒找到這個錯誤的原因。沒辦法,後面沒有使用addeventhandler這個方法了。自己利用osgutil寫了乙個拾取物件的函式。主要參考 使用osgutil polytopeintersecto...
opengl es 射線拾取
後來只好自己一點一點蒐集資料,但是無奈不知道為什麼網上這個內容有價值的特別特別少,但是好在這個過程中熟悉了android除錯過程,又找到了其他一些有用的東西,就寫了第乙個帖子 android平台下opengl學習例程 在第乙個帖子發完之後,很多開發者留了言,給了意見,我發現有些問題是大家都碰到的,討...
osgearth向量拾取
向量拾取是最近才做的功能,以前一直認為這個功能可能會很麻煩,原因呢 osgearth裡 估計所有的gis球中 是將向量光柵化成紋理貼到球上的,怎麼拾取一張上的一條線呢 osgearth的自帶例子裡沒有找到向量拾取的例子 最終這個功能畢竟是做出來了,這裡把自己的探索過程梳理一下.首先去google上搜...