2010-09-05 38 views
1
的鳥瞰或2.5D渲染

我正在開發一個轉由turn導航軟件,我用以下解決方案,使我的道路線爲2.5D或3D視圖問題的地圖

Draw 2.5D or 3D Map with C# from lines

然而,上述解決方案是針對作爲0 < X <寬度和0 <ÿ<高度視口內線相當好。然而,有些線條的點可能具有y或< 0或y> height或x> width,然後上述解決方案變得瘋狂。任何人都可以幫我弄清楚如何解決這個問題?

VVVV隨着3D算法VVVV

alt text

VVVV沒有3D算法VVVV

alt text

更新:: 使用此代碼

double x = p->x(); 
double y = p->y(); 

double t = -0.5; 
x = x - w/2; 
y = y - h/2; 
double a = h/(h + y* sin(t)); 
double u = a * x + w/2; 
double v = a * y * cos(t) + h/2; 

p->setX(u); 
p->setY(v); 
return p; 

的地圖變成像下面的 alt text

我想以後有什麼毛病Y的計算,當他們走的路超越負面價值。我正在使用Qt,並且在Qt渲染器上出現裂縫,這與我們原來的問題無關。

回答

4

問題是,您正在使用的轉換不會將直線映射到直線。相反,直線通常是拋物線。您可以看到,在示例圖像中,在2D視圖中,從上到下的或多或少直線的主幹道在2.5D視圖中轉換爲彎曲的道路。如果你把它們分解成更短的片段,你會發現在你的例子中「瘋了」的線條也是一樣的。

在數學上,你可以看到正在發生的事情通過返回變換你使用:

x_ = (x - w/2)*(t1+(y/h)*(t2-t1)) + w/2 
y_ = y 

如果我們在這條線表示的直線爲​​,然後點(ay+b,y)映射到(ay+b - w/2)*(t1+(y/h)*(t2-t1)) + w/2,y) 。這個表達式看起來很複雜,但是您可以看到它的計算結果類似(c*y^2+d*y+e,y),適合的值爲c,d,e,這是一個拋物線。

所以你最好的選擇是放棄這個轉換並切換到perspective transform

在你原來的問題中,你提到渲染圖像的非仿射變換太慢了。看起來你現在已經在渲染它們之前切換了線條,而且速度足夠快。你現在唯一需要做的就是改變轉換。

這是建議的變換。這是幾個步驟,並將您的2D(x,y)座標轉換爲一些2.5D(u,v)座標。我假設你正在使用C#。

t = 0.3 // tilt angle - try different values  
X = x - w/2 ; 
Y = y - h/2 ; 
a = h/(h + Y*Math.Sin(t)) ; 
u = a*X + w/2 ; 
v = a*Y*Math.Cos(t) + h/2 ; 

這裏有一個參數t,它定義了以弧度表示的傾斜量。我建議玩的價值在0.3左右,加號或減號。

我用鉛筆和紙做了這個,但沒有運行它,所以讓我知道如果這不起作用..總是有可能有一個轉錄錯誤。

更新:你要避免做出任何實體(直線,多邊形,等等),有一個點(x,y)這樣a非正。更好的是,爲了避免溢出,當a<epsilon時,應該避免繪圖,其中epsilon是一些小的正值,如0.05或0.1。

+0

是的,另外,不是繪製一條恆定厚度的線,而是繪製出源地圖座標中相應的多邊形(矩形)。使用變換映射這4個頂點以繪製多邊形(而不是簡單的線)。這將使道路越走越小,就像他們應該做的那樣。 – 2010-09-08 20:49:50

+0

@Tom,感謝您的輸入。 @brainjam,請你給我提供一個像x = ******或代碼片段的方程式嗎?我的弱數學使我無法從維基文章中獲得工作代碼。非常感謝 – VOX 2010-09-09 11:53:55

+0

@VOX,我添加了一個建議的轉換。 – brainjam 2010-09-09 15:17:28

0

該公式的問題是它允許投影的x值穿過中線(w/2)。當試圖建立一個透視變換模型時,這是不可取的,因爲線應該接近但不跨越一個消失點。此外,由於寫入公式的方式,此交叉發生在相機前面而不是後面,這導致不必要的僞像。嘗試這樣的代替:

 
halfW = w/2 
dx = (x - halfW) 
dy = (h - y) // y increases downwards 
// tune these constants to taste. 
top = 1.25 
bottom = 0.75 
lowerBound = 0.1 // Avoids divide by zero and perspective lines crossing midline 
x_ = (dx/max(lowerBound, (bottom + ((dy/h) * (top - bottom))))) + w/2