1

We are coding a small game from scratch using Qt, OpenGL (as well as glm library for CPU-side code) and C++.

Our code handling collision detection does most of its math with floating points. It seems to work perfectly fine when compiled on an ArchLinux distribution, but freezes / doesn't work on a Windows machine. (Underlying hardware of both machines unknown). However, none of the math is extremely precise; when checking floating point equality, we always check whether the absolute difference of the two floats are below some threshold, and that threshold is usually around 0.0001. Furthermore, we use a lot of floor operations.

Since we never check for huge precision though, I'm wondering why the result is so vastly different on our machines (ie non working on one)? I tried reading up on the topic, but what would be the best way to make floating point operations behave the same way across systems? Would trying to somehow make sure we use fixed-sized ints and floats be enough?

In particular, this part of our ray-casting code seems to be troublesome (it used to be a while loop without limit, but that made it freeze on my machine - adding a limit of 10 iterations made it still work accurately on the linux distribution, but completely inaccurately on my windows machine.) (The code is a bit out of context so not sure how helpful providing it will be, but without it the question would have been a bit too general)

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;
        }
    }
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Fly
  • 810
  • 2
  • 9
  • 28
  • Not sure this completely answers your question, but [a good read](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). –  Nov 19 '19 at 00:07
  • 3
    Floor operations on floating point are dangerous. The floor of 1.0 is 1.0. The floor of 0.99999999999999988897769753748434595763683319091796875 is zero. – Patricia Shanahan Nov 19 '19 at 00:29
  • As @PatriciaShanahan points out, casting a `float` to an `int` is inherently unstable. To get round this, you might try `(int)(current_cell[i]+0.5)` instead of `(int)current_cell[i]`. Try this and see if it works! – TonyK Nov 19 '19 at 01:12
  • Essentially, you want to keep your cell assignment boundaries at low probability points, because of the big effects of tiny rounding errors in numbers close to cell boundaries. Currently, you have them at integers, which tend to be high probability, especially in artificial test data. @TonyK's suggestion moves them to half way between pairs of integers. – Patricia Shanahan Nov 19 '19 at 01:19
  • @Chipster Thanks. I had actually read this article (and some other "famous" ones) before, but it unfortunately didn't help me resolve my problem... – Fly Nov 22 '19 at 22:22

0 Answers0