我的游戏需要移动一定的角度.为此,我通过sin和cos得到角度的矢量.不幸的是,罪和cos是我的瓶颈.我相信我不需要这么精确.是否有一个C sin&cos和查找表的替代品,它非常精确但速度非常快?
我发现了这个:
float Skeleton::fastSin( float x )
{
const float B = 4.0f/pi;
const float C = -4.0f/(pi*pi);
float y = B * x + C * x * abs(x);
const float P = 0.225f;
return P * (y * abs(y) - y) + y;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这似乎不起作用.当我使用这个罪而不是C罪时,我会得到明显不同的行为.
谢谢
查找表是标准解决方案.你也可以使用两个查找表来获得度数,一个用于十度数并使用sin(A + B)= sin(a)cos(b)+ cos(A)sin(b)
对于您fastSin(),您应该查看其文档以了解它的有效范围.您为游戏使用的单位可能太大或太小,并且缩放它们以适应该功能的预期范围可以使其更好地工作.
编辑:
其他人提到通过减去PI来使其进入所需的范围,但显然有一个函数要求fmod对浮点数/双精度进行模数除法,所以这应该这样做:
#include <iostream>
#include <cmath>
float fastSin( float x ){
x = fmod(x + M_PI, M_PI * 2) - M_PI; // restrict x so that -M_PI < x < M_PI
const float B = 4.0f/M_PI;
const float C = -4.0f/(M_PI*M_PI);
float y = B * x + C * x * std::abs(x);
const float P = 0.225f;
return P * (y * std::abs(y) - y) + y;
}
int main() {
std::cout << fastSin(100.0) << '\n' << std::sin(100.0) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我不知道有多贵fmod,所以我接下来会尝试快速的基准测试.
基准测试结果
我编译了这个-O2并使用Unix time程序运行结果:
int main() {
float a = 0;
for(int i = 0; i < REPETITIONS; i++) {
a += sin(i); // or fastSin(i);
}
std::cout << a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
结果是sin大约慢了1.8倍(如果fastSin需要5秒,sin需要9).准确性似乎也很好.
如果您选择了这条路线,请确保在(-O2在gcc中)进行优化编译.
我知道这已经是一个古老的话题,但对于有同样问题的人来说,这里有一个提示.
在2D和3D旋转中,很多时候,所有矢量都以固定的角度旋转.而不是调用循环cos()或sin()循环的每个循环,在包含值cos(angle)或sin(angle)已经的循环之前创建变量.您可以在循环中使用此变量.这样只需要调用一次函数.
| 归档时间: |
|
| 查看次数: |
12345 次 |
| 最近记录: |