光线投射算法中的精度问题

Posted

技术标签:

【中文标题】光线投射算法中的精度问题【英文标题】:Precision problems in raycasting algorithm 【发布时间】:2014-09-03 02:48:09 【问题描述】:

我正在编写一个光线投射引擎。

射线的起始位置由站在 2D 网格内的玩家的位置给出。

当向一个方向投射光线时,我必须确定光线相交的网格。

(对概念的深入描述在这里:http://www.permadi.com/tutorial/raycast/rayc7.html

有一点不准确,会引起一些麻烦。我认为问题是由于网格步数计算不正确引起的。

但是我缺乏解决这个问题的数学理解。

问题描述:

当光线向左移动时,网格相交步长与向右移动时的步长略有不同。

(为什么我还要关心这个?:当垂直和水平交叉点彼此靠近时,特别是在角落,这导致一些水平网格交叉点比垂直网格交叉点更远离玩家的问题。因为我是在垂直交叉处使用不同的纹理,水平墙的外观被破坏了,因为垂直纹理用于墙的一小部分,即使它是水平墙。)

这个问题是由我的算法缺陷引起的吗?这就是我计算第一个水平网格交点和网格步长的方法:

找到第一个网格交点:

if (current_angle > 180) 
    first_grid_horizontal_y = ((int)p.pos_y / Field::width) * Field::width + Field::width;
 else 
    first_grid_horizontal_y = ((int)p.pos_y / Field::width) * Field::width - 1;

first_grid_horizontal_x = p.pos_x + (p.pos_y - first_grid_horizontal_y) / tan( 180 - current_angle);

计算步长:

if (current_angle > 180) 
    grid_stepsize_horizontal_y = Field::width;
    grid_stepsize_horizontal_x = Field::width / tan(current_angle - 180);
 else 
    grid_stepsize_horizontal_y = -Field::width;
    grid_stepsize_horizontal_x = Field::width / tan(180 - current_angle);

如您所见,我总是使用“180 - 当前角度”来确定 x 值的方向。这会导致不准确吗?我需要更多地区分角度吗?

【问题讨论】:

【参考方案1】:

三角函数使用弧度,而不是度数。所以

tan(180 - current_angle)

应该看起来像

tan(Math.Pi - current_angle)

注意它等于

- tan(current_angle)

如果你的 current_angle 是度数:

current_angle_radians = current_angle_degrees * Math.Pi / 180

【讨论】:

是的,我制作了自己的 tan 函数,它可以将弧度转换为度数。我只是 postet tan() 以获得更好的可读性。【参考方案2】:

我认为你的不准确来自于向上时减去 1。

这背后的想法可能是您想获取块的最后一个像素的索引,但这是不必要的:您在这里进行浮点数学运算并且下一个水平交点的y值应该代表网格单元之间的线。如果向下,则表示到单元格的最高坐标;如果你往上走,它代表最低的坐标。

(旁白:(int) y / w 将向零舍入,因此仅适用于非负数。您可以考虑使用 floor(x / w)。)

【讨论】:

以上是关于光线投射算法中的精度问题的主要内容,如果未能解决你的问题,请参考以下文章

光线投射算法的MySQL实现?

光线追踪、光线投射、光线行进和路径追踪有啥区别?

使用光线投射的对象拾取

Unity 中的光线投射和计时器问题

光线投射中的方向向量

Hololens 2 的光线投射问题