【问题标题】:THREE .JS raycasting performance三.JS 光线投射性能
【发布时间】:2018-05-27 18:04:51
【问题描述】:

我试图在一个方向范围内沿着平面找到一个点到大型复杂网格的最近距离:

 for (var zDown in verticalDistances) {
    var myIntersect = {};  
   for (var theta = Math.PI / 2 - 0.5; theta < Math.PI / 2 + 0.5; theta += 0.3) {
                var rayDirection = new THREE.Vector3(
                    Math.cos(theta),
                    Math.sin(theta),
                    0
                ).transformDirection(object.matrixWorld);
                 //  console.log(rayDirection);

                _raycaster.set(verticalDistances[zDown].minFacePoint, rayDirection, 0, 50);
                //  console.time('raycast: ');
                var intersect = _raycaster.intersectObject(planeBufferMesh);
                //   console.timeEnd('raycast: '); // this is huge!!! ~ 2,300 ms

                //   console.log(_raycaster);
                //    console.log(intersect);
                if (intersect.length == 0) continue;
                if ((!('distance' in myIntersect)) || myIntersect.distance > intersect[0].distance) {
                    myIntersect.distance = intersect[0].distance;
                    myIntersect.point = intersect[0].point.clone();
                }
            }
// do stuff
}

将鼠标悬停在同一表面上时我得到了很好的结果,但是在执行此循环时,每次投射需要 2 秒以上的时间。我唯一能想到的是 DoubleSide 材料的背面要慢很多?

我还注意到,当我将verticalDistances[zDown].minFacePoint 隔开以使其相距更远时,光线投射开始加速(500 毫秒/投射)。因此随着verticalDistances[i].minFacePoint 和verticalDistances[i+1].minFacePoint 之间的距离增加,raycaster 的执行速度会更快。

我会走使用八叉树的路线,但鼠标悬停事件在完全相同的平面缓冲区上运行得非常好。这是材料问题的一面吗?可以通过加载 2 个指向相反方向的 FrontSide 网格来解决?

谢谢!!!!

编辑:这不是前后问题。我在平面缓冲区几何体的正面和背面运行我的光线投射,并获得相同的点结果。活生生的例子来了。

编辑 2:工作示例 here。性能略好于原始案例,但仍然太慢。我需要实时移动气缸。我可以通过查找某些东西来进行一些优化,但是鼠标悬停是即时的。当您查看控制台时间时,前两个(500 毫秒)是我得到的所有结果的结果。

编辑 3:添加了鼠标悬停事件,其执行与其他光线投射器相同。我在我的工作代码中没有得到我在这个示例中得到的结果。我得到的所有光线投射的结果与我在 500 毫秒左右的样本中的前 1 或 2 个得到的结果相同。如果我能把它降低到 200 毫秒,我可以瞄准我正在寻找的项目并减少光线投射。我完全愿意接受有关更好方法的建议。八叉树是要走的路吗?

raycast: : 467.27001953125ms
raycast: : 443.830810546875ms

编辑 4:@pailhead 这是我的计划。 1.找到最近的网格顶点指向平面。我可以在 x/y 方向扫描顶点,然后计算最小距离。 2.一旦我有了最近的顶点,我就知​​道我最近的点必须在包含该顶点的面上。因此,我将使用 object.mesh.index.array 找到具有该顶点的所有面,并计算每个面的平面到点。与网格相交并至少根据最大距离剔除点时,似乎光线投射应该比完全扫描更智能一点? @WestLangley 有什么建议吗?

编辑 5: @pailhead 谢谢你的帮助。其赞赏。我真的简化了我的example

编辑 6:看起来所有网格在 raycast 函数中的处理方式相同。这意味着它不会聪明地寻找平面缓冲区几何的区域。查看mesh.js 第 266 行,我们遍历整个索引数组。我猜对于常规网格,您不知道哪些面在哪里,因为它是 TIN,但是 planeBuffer 可以真正使用边界框/球体规则,因为您的 x/y 是已知的顺序位置,只有 Z 是未知的。最后编辑,答案将在下一个

【问题讨论】:

  • 为什么你认为背面或正面应该重要?你能发布一些实时代码吗?
  • 现在正在处理示例。正面/背面没有区别。从相机和鼠标设置光线投射然后从点方向设置光线投射有区别吗?我标准化了我的 Ray 方向,认为可能是一些奇怪的浮点问题。谢谢。将在几个小时后返回示例
  • @pailhead link
  • FWIW,当光线投射器尝试与背面相交时,它只是简单地重新排列面的顶点,这是一个微不足道的操作。
  • 您正在对一个具有 300k 个面的对象执行数十次光线投射。这就是为什么它很慢。

标签: javascript three.js raycasting


【解决方案1】:

仅供参考:为了获得最大速度,您可以使用数学。无需使用光线投射。 https://brilliant.org/wiki/3d-coordinate-geometry-equation-of-a-plane/

【讨论】:

  • 这不是平面。这是一个为每个“节点”添加高程的平面。我在想我可以找到最近的节点,然后使用您建议的方法开始循环连接到该节点的面,但它会给代码增加很多复杂性,希望我有一个简单的光线投射错误
  • 为什么它是一架飞机?我认为您的问题需要编辑。您有一个“网格”(或三个.js 土地中的“几何”),它源自平面的事实完全无关紧要。说“我对具有数十万个三角形的极其复杂的网格进行光线投射会更合适(12次)。
【解决方案2】:

解决的最大问题是根据顶点索引过滤掉 planeBufferGeometry 的面。使用planeBufferGeometry,您可以找到一个边界球体或矩形,为您提供需要检查的面。它们在索引数组中按 x/y 排序,以便过滤掉许多人脸。我在索引数组的左下角位置做了一个 indexOf 和 lastIndexOf 右上角的位置。光线投射检查每一张脸

我也放弃了寻找到对象每个面的距离,而是使用了沿着对象中心向下的垂直路径。这减少了所需的光线投射。

最后,我做了我自己的面部遍历,并在每张脸上使用了 traingle.closestPointToPoint() 函数。

每个点到表面计算(单次光线投射)大约需要 10 毫秒,每个对象(10 个垂直切片)到表面大约需要 100 毫秒。在优化之前,我看到每个光线投射 2.5 秒和每个对象 25 多秒。

【讨论】:

    猜你喜欢
    • 2018-07-10
    • 2016-01-10
    • 2016-11-09
    • 1970-01-01
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    相关资源
    最近更新 更多