質問

私はオクトリーを実装しようとしています。そのために、高速AABB線交差点アルゴリズムが必要です。いくつかの検索の後、私は出会いました これ それを提供しているように思われた紙。ソースコードから、利用可能 ここ, 、翻訳しました pluecker_cls_cff これとしてc#への関数:

public bool Intersect_2(ref RayPluecker r)
{
  switch (r.Classification)
  {

    // 7 same-ish cases snipped

    case Classification.PPP:

      return !((r.Position.X > this.Max.X) || (r.Position.Y > this.Max.Y) || (r.Position.Z > this.Max.Z) ||
        (r.PlueckerCoefficient.X + r.Direction.X * this.Max.Y - r.Direction.Y * this.Min.X < 0) ||
        (r.PlueckerCoefficient.X + r.Direction.X * this.Min.Y - r.Direction.Y * this.Max.X > 0) ||
        (r.PlueckerCoefficient.Y + r.Direction.X * this.Min.Z - r.Direction.Z * this.Max.X > 0) ||
        (r.PlueckerCoefficient.Y + r.Direction.X * this.Max.Z - r.Direction.Z * this.Min.X < 0) ||
        (r.PlueckerCoefficient.Z - r.Direction.Z * this.Min.Y + r.Direction.Y * this.Max.Z < 0) ||
        (r.PlueckerCoefficient.Z - r.Direction.Z * this.Max.Y + r.Direction.Y * this.Min.Z > 0));
  }

  return false;
}

これは正常に動作しているようですが、私にとってはかなり遅いように見えました(1000万の交差を行うには250ms)ので、さまざまな品種でマイクロベンチマークを試しました。 1つでは、直後にある否定を削除しました return ステートメントとすべての比較を逆転させた(>< およびVisa Versa)。

雪が降る:

case Classification.PPP:

      return ((r.Position.X < this.Max.X) || (r.Position.Y < this.Max.Y) || (r.Position.Z < this.Max.Z) ||
        (r.PlueckerCoefficient.X + r.Direction.X * this.Max.Y - r.Direction.Y * this.Min.X > 0) ||
        (r.PlueckerCoefficient.X + r.Direction.X * this.Min.Y - r.Direction.Y * this.Max.X < 0) ||
        (r.PlueckerCoefficient.Y + r.Direction.X * this.Min.Z - r.Direction.Z * this.Max.X < 0) ||
        (r.PlueckerCoefficient.Y + r.Direction.X * this.Max.Z - r.Direction.Z * this.Min.X > 0) ||
        (r.PlueckerCoefficient.Z - r.Direction.Z * this.Min.Y + r.Direction.Y * this.Max.Z > 0) ||
        (r.PlueckerCoefficient.Z - r.Direction.Z * this.Max.Y + r.Direction.Y * this.Min.Z < 0));

これは同じ結果をもたらすはずですよね?いくつかのテストケースで否定されたバージョンと同じ結果を返すため、そう思われました。ただし、ベンチマークでは、5倍高速でした(1,000万の交差を行うには50ms)!私はそれが最適化されていなかったと確信しています、私のベンチマークは次のように見えます:

for (int i = 0; i < 10000000; i++)
{
  if (!box.Intersect_3(ref ray))
  {
    throw new Exception();
  }
}

この大きな違いを説明できるものは何ですか? x86で.net 4.0を実行しています。

役に立ちましたか?

解決

2番目のコードは、最初のコードと同じことをしません。

すでに行った変更に加えて、すべてのORをAndsに変える必要があります。 (見る デ・モーガンの法律.)

修正を行った後、2つのバージョンが同じ速度で実行されることは間違いありません。

他のヒント

パフォーマンスに特に関連して、2番目のケースよりも早くリターンステートメントが短絡するのは、最初のケースよりも短絡です。比較の順序を変更しようとする価値があるかもしれません。 ||の代わりに&&を使用して計算を同等に変更する場合2番目のケースでは、虚偽のものが最初に来る可能性が最も高いものが必要です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top