三.S。光线投射表现

问题描述 投票:0回答:2

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

 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材料的BackSide慢一点?

另外我注意到,当我将verticalDistances [zDown] .minFacePoint分开时,光线投射开始加速(500ms / cast)。因此,当verticalDistances [i] .minFacePoint和verticalDistances [i + 1] .minFacePoint之间的距离增加时,raycaster执行得更快。

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

谢谢!!!!

编辑:这不是前面的问题。我在平面缓冲区几何体的正面和背面沿着相同的光斑结果运行我的光线投影。实例来了。

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

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

raycast: : 467.27001953125ms
raycast: : 443.830810546875ms

编辑4:@pailhead这是我的计划。 1.找到最近的网格顶点到平面上的点。我可以在x / y方向上扫描顶点然后计算最小距离。 2.一旦我有最近的顶点我知道我的最近点必须在包含该顶点的面上。因此,我将使用object.mesh.index.array找到具有该顶点的所有面,并计算每个面的平面点。看起来像光线投射应该比网格交叉时的全扫描更聪明,并且至少基于最大距离的剔除点? @WestLangley有什么建议吗?

编辑5:@pailhead感谢您的帮助。它赞赏。我真的简化了我的example(<200行,有更多评论); raycaster检查每张脸?在构造函数中指定的设置光线投射范围内选择面并更快地进行面对点计算。这不应该是在每个面部循环到光线投射。在源代码达到峰值并检查八叉树之后,我今晚将编写自己的PlaneBufferGeometry光线投射功能。我想如果我们在raycaster构造函数中有一个范围,则在该范围内拉出平面缓冲区顶点而忽略z。然后只是光线投射那些或做点平面计算。我想我可以从那个边界圆圈创建一个“迷你”表面然后用它进行光线投射。但是最大距离(手动使用“远”)不会影响raycaster的速度这一事实让我想知道它对planeBuffer几何的优化程度。 FYI你的300k循环在jsfiddle上约为3ms。

编辑6:看起来所有网格在光线投射功能中都被视为相同。这意味着它不会聪明地寻找一个平面Buffer Geometry的区域。看看mesh.js第266行,我们遍历整个索引数组。我猜对于常规网格你不知道哪些面是哪里因为它是一个TIN,但是一个planeBuffer确实可以使用一个边界框/球体规则,因为你的x / y是已知的顺序位置而只有Z是未知的。上次编辑,接下来是答案

javascript three.js raycasting
2个回答
1
投票

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

我也放弃了从物体的每个面找到距离,而是使用垂直路径沿着物体的中心。这减少了所需的射线铸件。

最后,我做了自己的面孔,并在每张脸上使用了triangle.closest PoinT Point()函数。

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


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.