2011-03-18 90 views

回答

3

我發現構建視錐體的世界空間模型並檢查bbox與它的碰撞是錯誤的方法。

更簡單的方法是以相反的方式將給定bbox的每個頂點轉換爲屏幕空間,並且如果bbox的任何頂點位於屏幕邊界內,則將該bbox計爲可見。我通過乘以相機矩陣得到屏幕空間位置,然後根據相機的視場計算透視圖。

下面的代碼:

vertexMatrix = matrix([vertex.x,vertex.y,vertex.z,1]) 
productMatrix = (vertexMatrix * camMatrix) 
pVectSS = vector(prodMatrix[0][0],prodMatrix[0][1],prodMatrix[0][2]) 

pointX = ((pVectSS.x/(-pVectSS.z))/tan(radians(hFOV/2)))/2.0+.5 
pointY = ((pVectSS.y/(-pVectSS.z))/tan(radians(vFOV/2)))/2.0+.5 

鍵:

camMatrix = camera inverse world-space matrix 
pVectSS = position vector screen-space 
hFOV = horizontal field of view 
vFOV = vertical field of view 
1

,將工作。但是,通常人們寧願提取平截面,並計算距離。你說過「速度不是什麼大不了的」,但最終你會發現它是。畢竟,人們會爲了讓事情變得更快而進行平凡的挑戰。

將頂點與矩陣相乘需要相當於4點產品,因此您需要相當於32點產品來檢查所有8個角點。計算一個點到一個平面的距離需要一個點積和一個加法,在最糟糕的情況下效率更高,在平均情況下更有效率(因爲在一個或兩個平面之後裁剪之後通常會丟棄一個對象,並且從不超過三個)。對於利用臨時一致性的剪輯平面有很多優化,我不會深入細節。

此外,您可以預先通過計算中心點與平面的距離並檢查它是否大於邊界框的半徑來進行粗略剔除。這將非常便宜地剔除清楚地「進」或「出」的物體。或者,或者,您可以將視角矢量的點積與視場值的餘弦值加上一些「填充」(或者,看看它是否爲正數)作爲第一次超粗檢查。你會記得,兩個向量的點積告訴你它們指向相同方向的程度。某些與視圖矢量具有負面點積的東西肯定是您可以放心丟棄的東西,因爲它在您後面。

+0

嘿,謝謝你的回答達蒙。 – leohutson 2011-03-23 00:13:05

+0

我應該詳細闡述爲什麼速度不是這種情況下的一個因素;該腳本用於預處理3d場景以決定將哪些對象導出到光線跟蹤渲染器,因此在其運行速度並不重要的方案中,只需執行速度:)。我的回答實際上也有點錯誤,因爲有一個邊緣情況,一個大物體靠近相機,它的垂直點都在FOV之外,所以我最終只是在世界空間周圍繪製了屏幕空間bbox,這是一個非常糟糕的黑客,但現在已經夠好了。 – leohutson 2011-03-23 00:24:53

+0

對於光線追蹤器,即使只有少數幾個碎片在邊界處可能會產生巨大的差異。你可以考慮使用OpenGL來繪製你的場景(如果你願意,可以使用固定的功能,因爲速度並不重要,而且很容易),並且爲每個對象運行一個遮擋查詢(幾乎每一個顯卡都支持這個查詢,因爲至少有一半十年)。沒有z-測試,所以透明的對象不會剔除它們後面的東西,我們也不會對漂亮的渲染感興趣。我們只需要查詢中的正數就可以繪製出一個片段。 – Damon 2011-03-23 08:26:05