2010-10-28 77 views
10

正如所看到的圖像OpenGL GL_SELECT或手動碰撞檢測?

http://oi56.tinypic.com/ifu33k.jpg

我畫設定的輪廓(多邊形)如GL_LINE_STRIP英寸 現在我想要選擇鼠標下的曲線(多邊形)來刪除,移動..等三維。

我想知道使用哪種方法:

1.使用OpenGL的挑選和選擇。 (glRenderMode(GL_SELECT))

2.使用手動碰撞檢測,使用拾取光線並檢查光線是否在每個多邊形內。

+0

我感謝所有的答案,因爲我只能給賞金信貸一次選擇一個answer.I選擇科斯回答是正確的,因爲我已經實現並給予恩惠Redrobes,對幾何很好的解釋。謝謝大家。 – 2010-11-02 02:39:24

+0

研究Irrlicht是如何做的,例如1.8.1中的'./ 7.collision'就是這樣做的。 – 2016-04-14 15:02:37

+0

此操作的名稱是「光線投射」:https://unity3d.com/learn/tutorials/modules/beginner/physics/raycasting子彈物理學也可以做到這一點:http://bulletphysics.org/mediawiki-1.5 .8/index.php/Using_RayTest – 2016-04-14 21:59:41

回答

16

我強烈推薦針對GL_SELECT。在新的GL版本中,這種方法非常陳舊,並且您可能會遇到現代顯卡的問題。不要指望它被硬件支持 - 可能你會在許多GPU上遇到軟件(驅動程序)回退的問題,前提是它可以工作。請自擔風險:)

讓我爲您提供一個替代方案。

對於固體,大對象,有選擇的被一條古老的好辦法:

  • 啓用和在光標位置
  • 繪製屏幕,​​沒有照明的剪刀測試設置爲1x1的窗口,紋理和多重採樣,爲每個「重要」實體分配唯一的純色 - 此顏色將成爲拾取的對象ID
  • 調用glReadPixels並檢索顏色,然後用於識別拾取的對象
  • 清除t他緩衝,將剪刀重新設置爲正常尺寸並正常繪製場景。

這給你一個非常可靠的「按對象」揀選方法。另外,除非您的頂點處理能力不足(不太可能,我認爲),或者確實有很多對象,並且可能會獲得基於CPU的處理能力,綁定在繪製調用次數上(但是,如果可以按照像素數據傳遞顏色,我相信可以將這個優化轉化爲單次繪製調用)。

RGB中的顏色是3個無符號字節,但應該可以額外使用framebuffer的alpha通道作爲最後一個字節,所以總共可以得到4個字節 - 足以存儲任何32位指針作爲顏色的對象。

或者,您可以創建一個具有特定像素格式的專用幀緩衝區對象(如GL_R32UI或甚至GL_RG32UI,如果您需要64位)。

對於嚴格的幾何方法,以上是一個很好且快速的替代方案(無論是在可靠性還是在實施時間方面)。

+0

感謝您的答覆。請問這種方法適用於輪廓線(線)嗎?因爲我沒有渲染實心多邊形? – 2010-11-01 01:31:43

+0

這意味着,我必須渲染對象兩次?b先抽取顏色,然後讀取像素值。然後以正常方式渲染? – 2010-11-01 09:47:44

+1

是的,沒錯。你繪製每個對象兩次。由於在拾取階段,您只能重畫屏幕的一個像素(因爲glViewport),所以這不應該是性能問題。關於輪廓工作 - 基本上如果你畫線而不混合等,它應該完美地工作,唯一的缺點是用戶需要精確地點擊線條本身。您可能需要放大采摘階段的glLineWidth。這是你期望的行爲嗎? – Kos 2010-11-01 12:57:00

0

第一個是易於實施和廣泛使用。

1

在過去,我使用GL_SELECT來確定哪個對象貢獻了感興趣的像素,然後使用計算幾何來獲得與對象的精確交集(如果需要的話)。

1

您是否期望通過單擊輪廓(在邊緣上)或多邊形內部進行選擇?你的第二種方法聽起來像你想要在內部點擊選擇最緊密的包含多邊形。我不認爲在渲染GL_LINE_STRIP後會讓內部響應點擊。如果這是一個真實的等高線圖(從圖像中我不認爲它是邊緣看起來相交),那麼可以使用更簡單的算法。

5

我發現在新的GPU上,GL_SELECT模式非常慢。我用幾種不同的方法來解決這個問題。

首先是做一個CPU的碰撞測試,它的工作,但沒有我想要的那麼快。當您將光線投射到屏幕上時(使用gluUnproject),然後嘗試查找鼠標與哪個對象發生碰撞,它肯定會變慢。我得到令人滿意的速度的唯一方法是使用八叉樹來減少碰撞測試的次數,然後進行邊界框碰撞測試 - 但是,這導致了一種沒有像素完美的方法。

我決定的方法是首先找到鼠標下的所有對象(使用gluUnproject和邊界框碰撞測試),這通常非常快。然後,我將後緩衝器中可能與鼠標碰撞的每個對象渲染爲不同的顏色。然後,我使用glReadPixel獲取鼠標下的顏色,並將其映射回該對象。 glReadPixel是一個緩慢的調用,因爲它必須從幀緩衝區讀取數據。但是,它每幀完成一次,最終花費的時間可以忽略不計。如果你願意的話,你可以通過渲染到PBO來加速它。

Giawa

1

您不能使用選擇,如果你留在行,因爲你必須單擊上呈現不,我看你想要做的事情定界的行內的空間行像素。

你可以使用科斯的答案,但爲了渲染你需要的空間來填充它,這將涉及到所有的輪廓轉換爲凸的類型,這是痛苦的。所以我認爲這有時會起作用,並在某些情況下給出錯誤的答案,除非你這樣做。

你需要做的是使用CPU。您可以從視口和透視矩陣獲得視圖範圍。使用鼠標座標,生成鼠標指針矢量的視圖。你也擁有所有等高線的座標。

取第一個輪廓的第一個座標,並向第二個座標做一個矢量。從他們身上製作一個矢量。取第3個座標並從2到3製作一個矢量,然後在輪廓周圍重複,最後使座標n的最後一個再次回到0。對於每一對順序找到交叉產品並總結所有結果。當你有最後的求和矢量保持這一點,並用鼠標指針方向矢量做點積。如果它的+ ve,那麼鼠標在輪廓內,如果它的-ve那麼它不是,如果是0,那麼我猜輪廓平面和鼠標方向是平行的。

爲每個輪廓做一個這樣的事情,然後你就會知道你的鼠標中哪些是尖刺的。它取決於你想從哪一個中選擇哪一個。最高Z?

這聽起來像很多工作,但它不是太糟糕,會給出正確的答案。您可能還需要保留所有輪廓的邊界框,然後通過執行與完整矢量相同的數學運算,但只能在4邊上進行,並且如果不在其內部,則可以通過執行相同的數學運算,從而早日退出鼠標矢量的輪廓,無論是。

+0

謝謝你的回答。我的輪廓沒有統一的方向。一些輪廓是順時針方向的,而另一些則是逆時針方向。我是否必須根據方向改變交叉產品操作? – 2010-11-01 01:39:12

3

umanga,看不出如何在線回覆......也許我應該簽了:)

首先我必須給你錯誤的算法中道歉 - 我做的背面剔除之一。但是你需要的是非常相似的,這就是爲什麼我很困惑...哦。

如前所述,將相機位置獲取到鼠標矢量。

在它

對於對每個輪廓,遍歷所有COORDS(0-1,1-2,2-3,...,N-0)並如前進行VEC了出來。即走輪廓。

現在做這兩個(輪廓邊緣到鼠標VEC)的橫PROD代替對之間像前面所說,做到這一點對所有的對和矢量添加它們加起來。

最後找到結果向量的大小。如果結果爲零(考慮到舍入誤差),那麼你的形狀就在外面 - 不管面對什麼。如果你有興趣面對那麼而不是mag,你可以用鼠標向量來找到面對並測試符號+/-。

它的工作原理是因爲算法依次找到從矢量線到每個點的距離。當你總結他們,你在外面,那麼他們都取消了,因爲輪廓是封閉的。如果你在裏面,那麼他們都總結。它實際上是物理中高斯電磁場的定律......

請參閱:http://en.wikipedia.org/wiki/Gauss%27s_law注意:「等式的右邊是由S除以電常數「,注意」封閉「一詞 - 即零表示不封閉。

對於速度,您仍然可以使用邊界框進行優化。