我正在尝试实现OCTREE,为此,我需要快速的AABB-ray交叉点算法。搜索后,我遇到了 似乎提供的纸。从源代码可用 这里, ,我翻译了 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;
}

这似乎很好,但是对我来说似乎相当慢(250毫秒来进行1000万个相交),所以我尝试了一些具有不同品种的微基准测试。在一个中,我删除了在此之后的否定 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倍(50毫秒来完成1000万个相交)!我敢肯定它没有被优化,我的基准看起来像这样:

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

什么可以解释这种巨大的差异?我在x86上运行.NET 4.0。

有帮助吗?

解决方案

您的第二个代码与第一个代码没有相同的事情。

除了您已经进行的更改之外,您还需要将所有ORS变成和变成。 (看 摩根的法律.)

我敢打赌,在您进行修复后,您的两个版本将以相同的速度运行。

其他提示

我敢打赌,在第二种情况下,我敢打赌,返回语句比第一种情况更快。如果有些人比其他人更有可能是真实的,则可能值得尝试更改比较的顺序。如果将计算更改为使用&&而不是||在第二种情况下,您将希望最有可能是假的人。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top