首页 > 解决方案 > 防止跨系统的浮点运算差异

问题描述

我们正在使用 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;
        }
    }
}

标签: c++mathfloating-pointgame-physics

解决方案


推荐阅读