c++ - 防止跨系统的浮点运算差异
问题描述
我们正在使用 Qt、OpenGL(以及用于 CPU 端代码的 glm 库)和 C++ 从头开始编写一个小游戏。
我们的代码处理碰撞检测的大部分数学运算都使用浮点数。在 ArchLinux 发行版上编译时,它似乎工作得很好,但在 Windows 机器上冻结/不起作用。(两台机器的底层硬件未知)。然而,没有一个数学是非常精确的。在检查浮点相等时,我们总是检查两个浮点数的绝对差是否低于某个阈值,该阈值通常在 0.0001 左右。此外,我们使用了大量的地板操作。
由于我们从不检查巨大的精度,我想知道为什么我们的机器上的结果如此不同(即不能在一台机器上工作)?我尝试阅读该主题,但是使浮点操作在系统中以相同方式运行的最佳方法是什么?尝试以某种方式确保我们使用固定大小的整数和浮点数就足够了吗?
特别是,我们的光线投射代码的这一部分似乎很麻烦(它曾经是一个没有限制的while循环,但这使它在我的机器上冻结了——添加了10次迭代的限制使它在linux发行版上仍然可以正常工作,但在我的 Windows 机器上完全不准确。)(代码有点脱离上下文,所以不确定提供它会有多大帮助,但如果没有它,问题会有点过于笼统)
while (abs(ray_dist) < proposed_dist) {
max_iterations--;
if (max_iterations <= 0) {
break;
}
float min_dist = 2; //greater than root(3)
//for each "plane"
for (int i=0; i<3; i++) {
if (ray_dir[i] != 0) {
//get new distance from ray origin to cell
float new_dist = ((current_cell[i] + ray_sign[i])
- current_ray_orig[i]) / ray_dir[i];
if (abs(new_dist) < min_dist) {
min_dist = abs(new_dist);
axis = i;
}
}
}
ray_dist += min_dist;
current_ray_orig += (ray_dir * min_dist);
//calculate main direction
glm::vec3 offset(0,0,0);
offset[axis] = opp_ray_sign[axis];
//get the current cell and the blocktype at the current cell
current_cell = glm::floor(current_ray_orig) + offset;
BlockType type_at_cell = terrain->getBlockAt((int) current_cell[0],
(int) current_cell[1],
(int) current_cell[2]);
//check if cell is considered to be empty
if (type_at_cell != EMPTY && type_at_cell != UNLOADED) {
//set position
if (ray_dist < shortest_dist) {
//to avoid floating pt clipping, set actual ray dist below possible ray dist
shortest_dist = abs(ray_dist) * .999f;
}
}
}
解决方案
推荐阅读
- batch-file - 如何刷新bat文件中的可用文件
- vagrant - 用于在具有 forward_port 80、8080 的 vagrant 中配置 vm 的 Vagrantfile 抛出错误
- java - 如何将arraylist方法用于另一种方法?
- javascript - 无法从 DOM 中的 datalist 对象访问列表属性
- azure-devops - Azure DevOps 拉取请求行颜色
- sharepoint - SharePoint 计时器作业在密码更改后停止工作
- google-apps-script - 将变量内容添加到 HTML 模板中的文本区域
- javascript - 如何在 React js 中获取开始日期和当前月份的日期?
- javascript - 在不刷新页面的情况下更改 URl NEXT.JS
- javascript - 解析充满字符串的对象时 JSON 解析出现 CORS 错误