现代游戏控制器可以指向广泛的方向。游戏设计者有时希望将摇杆方向转换为 8 向运动。提供的典型解决方案是计算角度,将其四舍五入,然后计算回方向向量。
双角= atan2 ( y , x ) ; 角度= ( int (圆( 4 *角度/ PI + 8 ) ) % 8 ) * PI / 4 ; xout = cos (角度) ; yout = sin (角度) ;
如果假设方向向量在第一象限(x 和 y 都是正数),那么有一种直接的方法可以计算解。使用 1/sqrt(2) 或 0.7071 作为默认解,将 x 和 y 与 cos(3*pi/8) 和 cos(pi/8) 进行比较,如果它们大于 cos,则仅将它们切换为 1 或 0 (3*pi/8) 或小于 cos(pi/8)。完整代码如下所示:
xout = 0.7071067811865475 ; 你= 0.7071067811865475 ; if ( x > = 0.923879532511286 ) { // cos(3*pi/8) xout = 1 ; } if ( y > = 0.923879532511286 ) { // cos(3*pi/8) 你= 1 ; } if ( x < 0.3826834323650898 ) { // cos(pi/8) xout = 0 ; } if ( y < 0.3826834323650898 ) { // cos(pi/8) 你= 0 ; }
您可以通过首先取绝对值,然后在末尾恢复符号来概括 x 或 y(或两者)为负的情况的解决方案:
布尔 xneg = x < 0 ; 布尔 yneg = y < 0 ; 如果( xneg ) { x = - x ; } 如果( yneg ) { y = - y ; } 双输出= 0.7071067811865475 ; 双重输出= 0.7071067811865475 ; if ( x > = 0.923879532511286 ) { // cos(3*pi/8) 输出= 1 ; } if ( y > = 0.923879532511286 ) { // cos(3*pi/8) 外= 1 ; } if ( x < 0.3826834323650898 ) { // cos(pi/8) 输出= 0 ; } if ( y < 0.3826834323650898 ) { // cos(pi/8) 外= 0 ; } 如果( xneg ) { 输出= -输出; } 如果( yneg ) { outy = - outy ; }
我写了一个在随机输入上运行的小基准。你的结果会有所不同,但在我的带有 LLVM 12 的 mac 笔记本电脑上,我知道直接方法要快 25 倍。
有切线 | 40 纳秒/向量 |
快速方法 | 1.5 纳秒/向量 |
原文: https://lemire.me/blog/2022/07/24/round-a-direction-vector-to-the-nearest-8-way-compass/