2014-08-31 46 views
0

假設有一個由兩個由三個頂點構成的瓷磚組成的遊戲的網格地形。我們如何找到四個頂點之間的Y(上)位置?如何找到四個頂點之間的Y點? HLSL

Terrain

我已經試過這樣:

float diffZ1 = lerp(heights[0], heights[2], zOffset); 
float diffZ2 = lerp(heights[1], heights[3], zOffset); 
float yPosition = lerp(diffZ1, diffZ2, xOffset); 

其中Z/Y偏移是z/y的百分比/ 100瓦的第一個頂點這適用於平坦的表面,但不能抵消在顛簸的地形上如此之好。

我想這與三角形的地形有關,上面的三角形可能在平面上工作。我不確定,但有人知道發生了什麼問題嗎?

這可以更好地解釋什麼是怎麼回事:

enter image description here

在上面的代碼「高度[]」是Y的陣列的周圍頂點座標v0-3。 三角1由頂點0,2和1。 三角2由頂點1,2和3

我希望能夠找到座標P1 Y的時,其x,y座標v0-3之間鋪設的。

所以我試圖確定的一點是通過這個函數三角:

bool PointInTriangle(float3 pt, float3 pa, float3 pb, float3 pc) 
{ 
    // Compute vectors   
    float2 v0 = pc.xz - pa.xz; 
    float2 v1 = pb.xz - pa.xz; 
    float2 v2 = pt.xz - pa.xz; 

    // Compute dot products 
    float dot00 = dot(v0, v0); 
    float dot01 = dot(v0, v1); 
    float dot02 = dot(v0, v2); 
    float dot11 = dot(v1, v1); 
    float dot12 = dot(v1, v2); 

    // Compute barycentric coordinates 
    float invDenom = 1.0f/(dot00 * dot11 - dot01 * dot01); 
    float u = (dot11 * dot02 - dot01 * dot12) * invDenom; 
    float v = (dot00 * dot12 - dot01 * dot02) * invDenom; 

    // Check if point is in triangle 
    return (u >= 0.0f) && (v >= 0.0f) && (u + v <= 1.0f); 
} 

這不是給我,結果我的預期

話,我想找到的y座標每個三角形內點p1:

// Position of point p1 
float3 pos = input[0].PosI; 

// Calculate point and normal for triangles 
float3 p1 = tile[0]; 
float3 n1 = (tile[2] - p1) * (tile[1] - p1); // <-- Error, cross needed 
     // = cross(tile[2] - p1, tile[1] - p1); 
float3 p2 = tile[3]; 
float3 n2 = (tile[2] - p2) * (tile[1] - p2); // <-- Error 
     // = cross(tile[2] - p2, tile[1] - p2); 
float newY = 0.0f; 

// Determine triangle & get y coordinate inside correct triangle 
if(PointInTriangle(pos, tile[0], tile[1], tile[2])) 
{ 
    newY = p1.y - ((pos.x - p1.x) * n1.x + (pos.z - p1.z) * n1.z)/n1.y; 
} 
else if(PointInTriangle(input[0].PosI, tile[3], tile[2], tile[1])) 
{ 
    newY = p2.y - ((pos.x - p2.x) * n2.x + (pos.z - p2.z) * n2.z)/n2.y; 
} 

使用下面找到第e正確的三角形:

if((1.0f - xOffset) <= zOffset) 
    inTri1 = true; 

而糾正上面的代碼使用正確的交叉函數似乎已經解決了這個問題。

enter image description here

+0

因此,如果您的座標位於第一個或第二個三角形的內部,這很重要嗎? – usr2564301 2014-08-31 22:28:27

+0

如果你使用'xOffset'等變量定義了四個頂點,這將更加清晰,特別是,如何從四個頂點創建兩個三角形?兩個三角形之間是否共享兩個頂點? – aecolley 2014-08-31 22:31:40

+2

是,兩個頂點是共享的,我有點理解爲什麼它不起作用,因爲有兩個三角形而不是一個扁平的正方形。我應該按照三角形檢查它嗎? – 2014-08-31 22:41:28

回答

3

因爲你的4個頂點可能不是在一個平面上,你應該分別考慮每個三角形。首先找到該點所在的三角形,然後使用以下StackOverflow討論來求解Z值(注意軸的不同命名)。我個人比較喜歡DanielKO的回答要好得多,但接受的答案應太:

Linear interpolation of three 3D points in 3D space


編輯:對於您的問題的第二部分(找到三角的一點是在): 因爲你的瓷磚投影到xz平面上(當你定義你的座標時)是完美的正方形,找到該點所在的三角形是一個非常簡單的操作。在這裏,我將使用左右的術語來指代x軸(從x的較低值到較高值)以及從底部到頂部來指代z軸(從z的較低值到較高值)。

每個圖塊只能以兩種方式之一分割。 (A)通過從左下角到右上角的對角線,或(B)通過從右下角到左上角的對角線。

  • 對於用於分割爲A的任何瓷磚: 檢查如果x「> Z」,其中x「是從的距離離開平鋪到點的邊緣,且z」是從距離將瓦片的邊緣點設爲底部。如果x'> z'那麼你的點位於右下三角形中;否則它在左上角的三角形中。

  • 對於每個已拆分爲B有塊:檢查是否X」> Z」,其中x」是從瓷磚到該點的邊緣的距離,和Z」是從底部的距離瓦片的邊緣點。如果x」> Z」那麼你的點是在左下角的三角形,否則它在右上角的三角形

(小注:以上我假設你的磚不會在XZ平面旋轉。 ;即它們與軸線對齊,如果不正確,只需旋轉它們使其與軸線對齊,然後再進行上述檢查。)

+0

好吧,我已經看過兩個答案,並會嘗試執行一個 – 2014-08-31 23:48:56

+0

讓我知道你是否需要任何幫助。 – Arda 2014-09-01 00:11:50

+0

我試圖關注DanielKO的答案,但我只是在確定點是否在一個三角形或其他三角形內時纔有問題。我怎樣才能做到這一點?每個三角形都有一個點和一個法線。 'FLOAT3 P1 =瓦片[0];' 'FLOAT3 N1 =(瓦[2] - P1)*(瓦[1] - P1);' 'FLOAT3 P2 =瓦片[3];' 'FLOAT3 n2 =(tile [2] - p2)*(tile [1] - p2);' – 2014-09-01 00:58:33

相關問題