0

4 つの頂点からなる 2 つの三角形からなるタイルで構成されるゲーム用のグリッド テレインがあるとします。4 つの頂点の間のポイントの Y (上) 位置をどのように見つけますか?

地形

私はこれを試しました:

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

z/yOffset は、タイルの最初の頂点からの z/y オフセット (パーセント / 100) です。

これは、上記が平面で機能する可能性のある三角形から作成された地形に関係していると思います。よくわかりませんが、何が問題なのか知っている人はいますか?

これは、ここで何が起こっているかをよりよく説明するかもしれません:

ここに画像の説明を入力

上記のコードで、"heights[]" は周囲の頂点 v0-3 の Y 座標の配列です。三角形 1 は頂点 0、2、1 で構成されています。三角形 2 は頂点 1、2、3 で構成されています。

x、y座標がv0-3の間にあるときに、p1の座標Yを見つけたいと思います。

そこで、この関数を使用して、ポイントがどの三角形の間にあるかを判断しようとしました:

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);
}

これは私が期待した結果を与えていません

次に、各三角形内の点 p1 の y 座標を見つけようとしています。

// 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;
}

以下を使用して、正しい三角形を見つけます。

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

上記のコードを正しいクロス関数を使用するように修正すると、問題が解決したようです。

ここに画像の説明を入力

4

1 に答える 1

4

4 つの頂点が平面上にない可能性があるため、各三角形を個別に検討する必要があります。最初にポイントが存在する三角形を見つけてから、次の StackOverflow の説明を使用して Z 値を解決します (軸の名前が異なることに注意してください)。私は個人的にDanielKOの答えがはるかに好きですが、受け入れられた答えもうまくいくはずです:

3D 空間における 3 つの 3D ポイントの線形補間


編集:問題の2番目の部分(ポイントが含まれる三角形を見つける): xz平面へのタイルの投影(座標を定義するとき)は完全な正方形であるため、ポイントが存在する三角形を見つけることは非常に簡単な操作。ここでは、x 軸 (x の低い値から高い値へ) を参照するために左-右という用語を使用し、z 軸 (z の低い値から高い値へ) を参照するために下-上という用語を使用します。

各タイルは、2 つの方法のいずれかでのみ分割できます。(A) 左下隅から右上隅への対角線経由、または (B) 右下隅から左上隅への対角線経由。

  • A として分割されたタイルの場合: x' > z' かどうかを確認します。ここで、x' はタイルの左端からポイントまでの距離であり、z' はタイルの下端からポイントまでの距離です。x' > z' の場合、ポイントは右下の三角形にあります。それ以外の場合は、左上の三角形にあります。

  • B として分割されたタイルの場合: x" > z' かどうかを確認します。ここで、x" はタイルの右端からポイントまでの距離であり、z' はタイルの下端からポイントまでの距離です。x" > z' の場合、ポイントは左下の三角形にあり、それ以外の場合は右上の三角形にあります。

(注意: 上記では、タイルが xz 平面で回転されていない、つまり、軸に沿って配置されていると想定しています。正しくない場合は、上記のチェックを行う前に、単純に回転させて軸に合わせてください。)

于 2014-08-31T23:13:53.430 に答える