2017-06-24 7 views
2

私は自分の錐台カリングを行う方法にいくつか問題があります。現在の方法は間抜けで解決しますが、実際には奇妙な効果があります。私が主な親オブジェクトに近づくと、シーングラフを使ってすべてをレンダリングしています。オブジェクトは本当に速くちらつき始めます。私が離れるとこれはなくなってしまいます。私は多くのことを試しましたが、アイデアはもうありません。皆さんにはどんな考えがありますか?どんな助けでも大歓迎です。現在の錐体のカリング効果により、openTkのオブジェクトが点滅します

まず、私のモデルの周りに8点からなるバウンディングボックスを作成します。これらは、私が多くのテストの後に気づいている限り正しいです。

これは、円錐台の点の計算方法です。 カメラ位置はワールド空間内の位置であり、向きは見ている方向です。さらに、cameraUpとcameraRightは、カメラが回転するたびに計算されます。

Vector3 pos = Camera.staticPosition; 
    Vector3 view = Camera.staticOrientation; 
    Vector3 upVector3 = Camera.cameraUp; 
    Vector3 rightVector3 = Camera.cameraRight; 
    float toRadians = (float)Math.PI/180.0f; 
    float nearDis = .1f; 
    float farDistance = 1000f; 
    float fov = Game.FOV; 
    float aspectRatio = 1.3f; 

    //Get with and height of near and far plane 
    float tanDiv = 2 * (float) Math.Tan(fov*toRadians/2); 
    float heightNear = tanDiv * nearDis; 
    float widthNear = heightNear * aspectRatio; 

    float heightFar = tanDiv * farDistance; 
    float widthFar = heightFar * aspectRatio; 

    // get the centre points of the planes so they can be used to calculate the edge points 
    Vector3 centreNear = pos + view * nearDis; 
    Vector3 centreFar = pos + view * farDistance; 

    // get the halfht values of the width and hegiht to make sure you can get the points 
    float hNearHalf = heightNear/2; 
    float wNearHalf = widthNear/2; 
    float hFarHalf = heightFar/2; 
    float wFarHalf = widthFar/2; 

    Vector3 nearTopLeft = centreNear + (upVector3 * hNearHalf) - (rightVector3 * wNearHalf); 
    Vector3 nearTopRight = centreNear + (upVector3 * hNearHalf) + (rightVector3 * wNearHalf); 
    Vector3 nearBottomLeft = centreNear - (upVector3 * hNearHalf) - (rightVector3 * wNearHalf); 
    Vector3 nearBottomRight = centreNear - (upVector3 * hNearHalf) + (rightVector3 * wNearHalf); 

    Vector3 farTopLeft = centreFar + (upVector3 * hFarHalf) - (rightVector3 * wFarHalf); 
    Vector3 farTopRight = centreFar + (upVector3 * hFarHalf) + (rightVector3 * wFarHalf); 
    Vector3 farBotomLeft = centreFar - (upVector3 * hFarHalf) - (rightVector3 * wFarHalf); 
    Vector3 farBottomRight = centreFar - (upVector3 * hFarHalf) + (rightVector3 * wFarHalf); 

私の錐台の点は配列に格納されます。まず、近平面の点、次に遠平面、トプレーン、ボトムプレーン、左面、最後に右面。次に、ポイントがプレーンの右側にある場合は、6つのプレーンとboundinboxの8ポイントのすべてをループして、辞書のそのキーの値を増やします。

Vector3[] frustumPoints = new Vector3[18] 
    { 
     nearTopLeft, nearTopRight, nearBottomLeft, farTopLeft, farTopRight, farBotomLeft, nearTopLeft, farTopLeft, 
     nearTopRight, nearBottomLeft, farBotomLeft, nearBottomRight, nearTopLeft, nearBottomLeft, farTopLeft, 
     nearTopRight, nearBottomRight, farTopRight 
    }; 
    Dictionary<Vector3, int> count = new Dictionary<Vector3, int>(8); 
    for (int value = 0; value < 8; value++) 
    { 
     count.Add(cubePositions[value], 0); 
    } 

    for (int x = 0; x < 18; x += 3) 
    { 
     Vector3 normal = NormalPlane(frustumPoints[x], frustumPoints[x + 1], frustumPoints[x + 2]); 

     for (int y = 0; y < 8; y++) 
     { 
      Vector3 pointPlane = frustumPoints[x] - cubePositions[y]; 
      float dot = Vector3.Dot(pointPlane, normal); 


      if (dot <= 0 && x % 6 == 0) 
      { 
       count[cubePositions[y]]++; 
      } 
      else if (dot >= 0 && x % 3 == 0) 
      { 
       count[cubePositions[y]]++; 
      } 

     } 
    } 

この

は、平面の法線を取得するための私の方法です

Vector3 NormalPlane(Vector3 pointOne, Vector3 pointTwo, Vector3 pointThree) 
{ 
    Vector3 normal; 
    Vector3 edgeOne = pointTwo - pointOne; // calculate vector from point one to point two 
    Vector3 edgeTwo = pointThree - pointOne; // calculate vector from point one to point three 

    normal = Vector3.Normalize(Vector3.Cross(edgeOne, edgeTwo)); // calculate the cross product of the two given vectors. Then normalize it so you have normal of plane 

    return normal; // return the normal 
} 

カウントが6である立方体、ポイント上のこれらの点のいずれかの全ての面ため、錐台内にある場合と、私はオブジェクトを描画します。ポイントのいずれも6に等しくなければ、オブジェクトは描画されません。

問題私は間違いをどこにしているのか分からないので、皆さんはアイディアを持っていますか?事前に

おかげで、

Jeromer

答えて

2

もしカウントが6であるキューブ上のこれらの点、点の一つは、全ての面内にあり、したがって、錐台と、私はオブジェクトを描画するために。ポイントのいずれも6に等しくなければ、オブジェクトは描画されません。

あなたのロジックがここに

  • のようだ「錐台内部にある立方体のない頂点が存在しない場合、キューブが表示されていません。」

ただし、これはただが間違ってです。錐台の外側キューブ嘘の全8つの頂点場合は、この2Dスケッチに示されているように、キューブは依然として、錐台と交差することができる:

    *----------* 
        |   | 
+-----------------+--+  | 
\    |/  | 
    \    |/   | 
    \   /  | 
    \   /|   | 
    \  /*----------* 
     \  /
     \ /
     +----+ 

したがって、あなたは、潜在的に見えるものを間引きます。

円錐台の一般的な論理は、すべての頂点が同じ平面でによって拒否された場合のみボックスを淘汰することです。 (これはボックスが完全に外にあり、淘汰されていないいくつかの奇妙なケースをもたらしますが、これらの状況はほとんどありませんし、通常心配することも大したことではありません。)

+0

お返事ありがとうございます。私はあなたが私に言ったことを試して実行します。そして、あなたは正しい、これは確かに私が考えていなかったものです。私が作ったこのエラーのために自分のメソッドをどのように変更するのかを理解するだけです。それを指摘してくれてありがとう! – Jeromer

+0

おかげでいくつかのものが修正されました。私は今、すべてのコーナーの最小値と最大値を計算し、最大値が錐台の最大値よりも大きいかどうかを見ています。もしそうなら、私は追い払う。問題は、私の親が淘汰されると、子供たちもまた淘汰されるということです。 – Jeromer

+0

階層カリングを行う場合は、階層境界ボリュームも必要です。 – derhass

関連する問題