青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 132  文章 - 51  trackbacks - 0
<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(7)

隨筆分類

隨筆檔案

文章分類

文章檔案

cocos2d-x

OGRE

OPenGL

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

使用OpenGL實現三維坐標的鼠標揀選
Implementation of RIP(Ray-Intersection-Penetration)
3D Coordinates Mouse Selection Using OpenGL
顧 露 (武漢理工大學 計算機系 中科院智能設計與智能制造研究所 湖北武漢 430070)
摘要(Abstract):
本文提出并實現一種用于三維坐標揀選的RIP(Ray-Intersection-Penetration)方法。介紹了如何在已經渲染至窗口的三維場景
中,使用鼠標或者相關設備揀選特定三維對象的方法。此方法對于正交投影或透視投影均有效,相對于OpenGL自帶的選擇與反饋機制,本方法無論是揀選精度
還是算法實現效率均高出許多,是一種比較通用的解決方案。關鍵詞(Keywords) 正交投影(Ortho-Projection)、透視投影(Perspective-Projection)
世界坐標系、屏幕坐標系、三維揀選、OpenGL
一、簡介(Introduction)
OpenGL是一種比較“純粹”的3D圖形API,一般僅用于三維圖形的渲染,對于特定領域的開發者(如游戲開發者)而言,如果選擇使用
OpenGL進行開發,類似碰撞檢測的機制就都需要自行編寫了。但是由于鼠標在圖形程序中的應用非常非常之廣泛(例如現在已經很少有PC游戲能完全地脫離
鼠標),OpenGL在圖形庫的基礎上添加了選擇與反饋機制(Select &
Feedback)來滿足用戶使用鼠標實時操作三維圖形的需要。但由于種種原因,我們需要更為特殊的選擇機制以滿足特定需求,在這里我們提出了一種簡單迅
速的RIP(Ray-Intersection-Penetration)方法,可以滿足絕大多數典型應用的需要。
二、相關研究(Related Work) 用過OpenGL選擇與反饋機制的開發者,或多或少可能都會覺得它難以令人滿意。大致表現在下面幾個方面:
一、 編寫程序比較繁瑣。
想要使用選擇反饋機制就需要切換渲染模式,操作命名堆棧,計算揀選矩陣,檢查選中記錄,這些繁瑣的步驟很容易出錯,而且非常不便于調試,只會降低工作效率和熱情。二、 只能做基于圖元的選定。

下圖(1 – a),使用GL_TRIANGLES繪制了一個三角形,三個頂點分別為
P1、P2和P3。若使用該機制,你將只能判斷是否在三維場景中選中了這個三角形(用戶點擊處是否在P1、P2和P3的范圍內),而無法判斷用戶是點擊了
這個三角形哪一部分(是左邊的m區域內還是右邊的n區域內),因為所繪制的P1、P2和P3本身構成的三角形就是一個基本圖元,對于揀選機制而言是不可分
的。當然,把這個三角形拆成兩個三角形再分別進行測試也是一個可行的方案,可是看看圖(1 – b),這可怎么拆呢?還有圖(1 –
c)呢?另外,如果n和m兩個平面不共面呢?對于使用者而言,OpenGL提供的揀選機制功能的確有限。

三、降低了渲染效率。
OpenGL
中的選擇和反饋是與普通渲染方式不同的一種特殊的渲染方式。我們使用時一般是先在幀緩存中渲染普通場景,然后進入選擇模式重繪場景,此時幀緩存的內容并無
變化。也就是說,為了選擇某些物體,我們需要在一幀中使用不同的渲染方式將其渲染兩遍。我們知道對對象進行渲染是比較耗時的操作,當場景中需要選擇的對象
多而雜的時候,采用這個機制是非常影響速度的。
另外在OpenGL紅寶書中介紹了一種簡便易行的辦法:在后緩沖中使用不同的顏色重繪所有對象,每個對象用一個單色來標示其顏色,這樣畫好之后我們讀取鼠
標所在點的顏色,就能夠確定我們揀選了哪個物體。這種方法有一個缺陷,當場景中需要選擇的對象的數目超出一定限度時,可能會出現標識數的溢出。對于這個問
題,紅寶書給出的解決辦法就是多次掃描。實踐證明這種方法的確簡便易行,但仍有不少局限性,而且做起來并不比第一種機制方便多少。限于篇幅,不再贅述。三、具體描述(Related Work) 看過了上面兩種方法,我們會發現這兩種方法都不是十分的方便,而且使用者不能對其進行完全的控制,不能精確地判定鼠標定位與實際的世界空間中三維坐標的關系。那么有什么更好的辦法能夠更簡單更精確地對其加以控制呢? 實際上此處給出的解決方案十分簡單,就是一個很普通也很有用的 GLU 函數 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),最后三個為輸出的世界坐標值。  可能你會問:窗口坐標不是只有X軸和Y軸兩個值么,怎么這里還有Z值?這就要從二維空間與三維空間的關系說起了。 
 眾所周知,我們通過一個放置在三維世界中的攝像機,來觀察當前場景中的對象。通過使用諸如gluPerspective()
這樣的OpenGL函數,我們可以設置這個攝像機所能看到的視野的大小范圍。這個視野的邊界所圍成的幾何體是一個標準的平截頭體(Frustum),可以
看做是金字塔狀的幾何體削去金字塔的上半部分后形成的一個臺狀物,如果還原成金字塔狀,就得到了通常我們所說的視錐(View
Frustum)這個視錐的錐頂就是視點(View Point)也就是攝像機所在的位置。平截頭體,視錐以及視點之間的關系,如下圖所示:

在上面的圖中,遠裁剪面ABCD和近裁剪面A’B’C’D’構成了平截頭體,加上虛線部分就是視錐,頂點O就是攝像機所在的視點。我們在窗口中所能看到的東東,全部都在此平截頭體內。這跟前面的窗口坐標Z值有什么關系呢?看下圖


此圖所示,點P和點P’分別在遠裁剪面ABCD和近裁剪面A’B’C’D’上。我們點擊屏幕上的點P,反映到視錐中,就是選中了所有的從點P到點P’的
點。舉個形象的例子,這就像是我們挽弓放箭,如果射出去的箭近乎筆直地飛出(假設力量非常之大近乎無窮),從挽弓的地點直至擊中目標,在這條直線的軌跡上
任何物體都將被一穿而過。對應這里的情況,用戶單擊鼠標獲得屏幕上的某一點,即是指定了從視點指向屏幕深處的某一方向,也就確定了屏幕上某條從O點出發的
射線(在圖中即為OP)。在這里,我們稱呼其為揀選射線。
因此,從窗口的XY坐標,我們僅僅只能獲得一條出發自O點的揀選射線,并不能得到用戶想要的點在這條射線上的確切位置。
這時候窗口坐標的Z值就能派上用場了。我們通過Z值,來指定我們想要的點在射線上的位置。假如用戶點擊了屏幕上的點(100,100)得到了這條射線OP,那么我們傳入值1.0f就表示近裁剪面上的P點,而值0.0f則對應遠裁剪面上的P’點。

樣,我們通過引入一個窗口坐標的Z值,就能指定視錐內任意點的三維坐標。與此同時,我們還解決了前面紅寶書給出的方法中存在的缺陷——同一位置上重疊物體
的選擇問題。解決辦法是:從屏幕坐標得到射線之后,分別讓重疊的物體與該射線求交,得到的交點,然后根據這些與視點的遠近確定選擇的對象。如此我們就不必
受“僅僅只能選取屏幕中離觀察者最近的物體”的限制了。這樣一來,如果需要的話,我們甚至可以用代碼來作一定的限定,通過判斷交點與視點的距離,使得與該
揀選射線相交的物體中,離視點遠的對象才能被選取,這樣就能夠對那些暫時被其他對象遮住的物體進行選取。
至于如何求揀選射線與對象的交點,在各種圖形學的書中的數學部分均有講述,在此不再贅述。
四、例程(Sample Code Fragment)

前面講述了RIP方法,現在我們來看如何編寫代碼以實現之,以及一些需要注意的問題。
由于揀選射線以線段形式存儲更加便于后面的計算,況且我們可以直接得到縱跨整個平截頭體的線段(即前面圖中的線段PP’),故我們直接計算出這條連接遠近裁剪面的線段。我們將揀選射線的線段形式稱之為揀選線段。
在下面的代碼前方聲明有兩個類Point3f和LineSegment這分別表示由三個浮點數構成的三維空間中的點,以及由兩個點構成的空間中的一條線段。
應注意代碼中用到了類Point3f的一個需要三個浮點參數的構造函數,以及類LineSegment的一個需要兩個點參數的構造函數。
獲取揀選射線的例程如下所示(使用C++語言編寫):class Point3f;
class LineSegment;
LineSegment GetSelectionRay(int mouse_x, int mouse_y) {
// 獲取 Model-View、Projection 矩陣 & 獲取Viewport視區
GLdouble modelview[16];
GLdouble projection[16];
GLint viewport[4];
glGetDoublev (GL_MODELVIEW_MATRIX, modelview);
glGetDoublev (GL_PROJECTION_MATRIX, projection);
glGetIntegerv (GL_VIEWPORT, viewport); GLdouble world_x, world_y, world_z; // 獲取近裁剪面上的交點
gluUnProject( (GLdouble) mouse_x, (GLdouble) mouse_y, 0.0,
modelview, projection, viewport,
&world_x, &world_y, &world_z);
Point3f near_point(world_x, world_y, world_z); // 獲取遠裁剪面上的交點
gluUnProject( (GLdouble) mouse_x, (GLdouble) mouse_y, 1.0,
modelview, projection, viewport,
&world_x, &world_y, &world_z);
Point3f far_point(world_x, world_y, world_z); return LineSegment(near_point, far_point);
}

如果你是使用Win32平臺進行開發,那么應當注意傳入正確的參數。因為無論是使用Win32 API 還是DirectInput
來獲取鼠標坐標,得到的Y值都應取反后再傳入。因為OpenGL默認的原點在視區的左下角,Y軸從左下角指向左上角,而Windows默認的原點在窗口的
左上角,而Y軸方向與OpenGL相反,從左上角指向左下角。如下圖所示:

我們可以看到代碼被注釋分為了三個部分:獲取當前矩陣及視區,獲取近裁剪面的交點,獲取遠裁剪面的交點。
我們通過OpenGL提供的查詢函數輕松得到當前的ModelView和Projection矩陣,以及當前的Viewport(視區,也就是窗口的客戶端區域,如果整個窗口區域用于OpenGL渲染的話)。
獲得兩個裁剪面上的交點的代碼基本上是一樣的,唯一的不同點是我們前面曾經詳細地討論過的窗口的Z坐標。不錯,這個坐標表示的就是“深淺”的概念。它的值從點P’到點P的變化是從0.0f逐漸增至1.0f。此處類似于OpenGL的深度測試機制。
在得到兩個交點之后,我們使用它們通過返回語句直接構建一條線段。在這里僅僅作為實例代碼,故簡捷清晰地直接返回線段對象,而沒有通過引用參數來提高效率。

時用戶可以使用這個函數來判斷所選擇的對象了。只需在需要的地方判斷對象是否與此線段相交即可判斷對象是否被選中,還可以通過進一步計算其交點位置來得到
詳細的交點信息。這些計算均是常見的計算機圖形學與三維數學計算,比如線段與三角形求交,線段與面求交,線段與球體求交,線段與柱體或錐體求交,等等。請
參考所列出的計算機圖形學書籍。
五、結論(Conclusion)

在本文中,我們介紹了一種行之有效的三維坐標拾取方法,主要使用GLU庫中的實用工具實現。這種方法速度快,效率高,能在不必重新繪制對象的前提下完成揀選工作。對比OpenGL自帶的揀選機制來看,RIP的確在各種方面均有一定的優勢。
六、參考文獻(Reference) 【1】《OpenGL Programming Guide》
OpenGL ARB Mason Woo, Jackie Heider, Tom Davis, Dave Shreiner
【2】《OpenGL Reference Manual》
OpenGL ARB
【3】《Computer Graphics》
Donald Heam, M. Pauline Baker
【4】《Computer Graphics using OpenGL 2nd Edition》
F.S. Hill, JR.
posted on 2010-06-05 18:45 風輕云淡 閱讀(3096) 評論(0)  編輯 收藏 引用 所屬分類: OpenGL
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品毛片高清在线完整版| 国产精品视频免费在线观看| 曰本成人黄色| 可以看av的网站久久看| 久久久欧美一区二区| 亚洲高清视频一区二区| 欧美激情视频在线播放| 欧美国产日韩视频| 一本大道av伊人久久综合| 99精品欧美一区| 国产乱子伦一区二区三区国色天香| 午夜欧美不卡精品aaaaa| 欧美一区二区三区在线| 在线观看亚洲专区| 91久久精品美女高潮| 国产精品毛片大码女人| 久久视频精品在线| 欧美精品粉嫩高潮一区二区 | 欧美精品久久久久久久久久| 中文日韩在线视频| 午夜亚洲伦理| 亚洲激情欧美激情| 亚洲午夜久久久| 雨宫琴音一区二区在线| 日韩一区二区福利| 国产综合视频| 亚洲精品国产精品乱码不99按摩| 国产九九精品视频| 欧美暴力喷水在线| 欧美性大战xxxxx久久久| 噜噜噜在线观看免费视频日韩 | 一区二区三区国产精品| 国产日韩欧美视频在线| 欧美激情在线| 国产亚洲午夜高清国产拍精品| 亚洲经典在线看| 国产一区二区三区久久悠悠色av| 亚洲精品日日夜夜| 国产真实乱偷精品视频免| 99香蕉国产精品偷在线观看| 狠狠色伊人亚洲综合网站色| 亚洲一区二区高清| 99视频精品| 欧美jizzhd精品欧美喷水| 久久大综合网| 国产精品久久国产愉拍 | 亚洲色图制服丝袜| 美女日韩欧美| 久久久蜜桃精品| 国产精品卡一卡二| 99ri日韩精品视频| 日韩午夜av| 麻豆freexxxx性91精品| 老司机免费视频久久| 国产女主播一区二区| 中国成人在线视频| 在线视频精品一区| 欧美另类人妖| 亚洲免费黄色| 亚洲手机视频| 欧美色精品天天在线观看视频| 亚洲激情啪啪| 日韩午夜av电影| 欧美精品激情blacked18| 欧美激情女人20p| 亚洲国产精品久久久久秋霞蜜臀| 久久色中文字幕| 牛牛影视久久网| 91久久在线观看| 欧美高清在线一区二区| 亚洲三级影片| 亚洲视频在线视频| 国产精品第2页| 亚洲制服少妇| 久久久久久亚洲精品中文字幕| 国产一区91| 久久婷婷国产综合精品青草| 免费看黄裸体一级大秀欧美| 亚洲国产精品va在线观看黑人| 你懂的视频欧美| 999亚洲国产精| 亚洲欧美国产精品专区久久| 国产精品一区久久久久| 欧美在线视频a| 亚洲高清网站| 亚洲综合精品四区| 国产偷久久久精品专区| 老司机精品视频网站| 亚洲日本va在线观看| 亚洲一区在线直播| 韩国av一区二区三区四区| 免费中文日韩| 亚洲伊人一本大道中文字幕| 美女视频网站黄色亚洲| 日韩一级片网址| 国产视频久久久久久久| 欧美成年网站| 亚洲免费在线视频| 亚洲国产成人av| 午夜在线视频观看日韩17c| 激情视频亚洲| 欧美日韩伊人| 久久久7777| 亚洲午夜激情| 欧美国产第二页| 午夜在线一区| 亚洲毛片av在线| 韩日成人在线| 欧美性大战久久久久| 麻豆av福利av久久av| 亚洲婷婷综合色高清在线| 欧美不卡视频一区发布| 午夜视频在线观看一区| 亚洲免费观看| 极品少妇一区二区三区精品视频| 欧美日韩成人在线播放| 久久久夜夜夜| 欧美呦呦网站| 中文一区二区| 日韩一级网站| 亚洲国产精品毛片| 免费看的黄色欧美网站| 欧美一级片久久久久久久| 亚洲久久在线| 亚洲国产精品黑人久久久| 国产三级欧美三级| 欧美性大战久久久久| 欧美国产精品劲爆| 另类天堂av| 久久久久欧美| 午夜宅男久久久| 亚洲免费人成在线视频观看| 99精品福利视频| 亚洲国产日韩欧美| 欧美激情网友自拍| 欧美黄色免费| 欧美大片国产精品| 毛片基地黄久久久久久天堂| 久久国产精品99精品国产| 午夜精品久久久久久久久| 一区二区三区波多野结衣在线观看| 亚洲欧洲视频| 亚洲激情视频在线播放| 亚洲国产精品久久久久| 亚洲成色777777在线观看影院| 国产综合在线看| 国产一区二区三区在线观看精品 | 国产精品免费看片| 国产精品萝li| 国产精品一区在线观看| 国产精品久久久久久影视| 国产精品男gay被猛男狂揉视频| 欧美性猛交xxxx免费看久久久 | 欧美成人午夜| 欧美精品色综合| 欧美日韩高清区| 国产精品国产| 国产日韩欧美三级| 亚洲电影av在线| 亚洲精品小视频| 一区二区三区精品国产| 午夜精品久久久久99热蜜桃导演| 校园激情久久| 快射av在线播放一区| 亚洲成人在线网| 一本大道久久a久久综合婷婷| 亚洲午夜黄色| 久久夜色精品国产亚洲aⅴ | 久久精品视频99| 久久在线精品| 欧美视频一区二| 国精产品99永久一区一区| 亚洲国产cao| 亚洲欧美精品在线| 麻豆成人精品| 99视频在线观看一区三区| 欧美亚洲视频在线观看| 毛片一区二区三区| 欧美午夜视频在线| 一区在线播放视频| 宅男噜噜噜66一区二区| 欧美一区二区三区喷汁尤物| 欧美99在线视频观看| 亚洲一区二区三区精品在线观看 | 麻豆精品精品国产自在97香蕉| 欧美另类视频| 激情av一区二区| 亚洲一区二区三区免费视频| 久久久久久一区二区三区| 亚洲乱码国产乱码精品精98午夜| 欧美在现视频| 欧美性猛交xxxx乱大交蜜桃| 亚洲大片av| 久久精品一区四区| 亚洲免费观看高清在线观看 | 亚洲五月六月| 欧美高清影院| 伊伊综合在线| 久久国产精品久久精品国产| 亚洲精品国精品久久99热一|