0

I am trying to calculate the surface normal of a triangle in C++ (and OpenGL) based on the 3 vertices of the triangle. I am getting correct results for a non rotated triangle, however I am getting semi-correct result for a rotated triangle. Not sure what I am doing wrong. The expected result should be returning a vector (1, 0, 0) for triangle 1 (non rotated) and (0, 0, -1) for triangle 2 (rotated 90 degrees on Y axis), however I get (1, 0, 0) for triangle 1 and (-4.15243e-08, 1.82413e-08, -1)

As you can see, the first vector and the Z component of the second normal vector is correct, however the X and Y components of the second vector are largely inaccurate as they should both be zero

My code is a very simple function making use of GLM:

void CalcSurfaceNormal(glm::vec3 tri1, glm::vec3 tri2, glm::vec3 tri3)
{
        //tri1 tri2 and tri3 are the triangles 3 vertices
        //Simple algorithm followed from another stack overflow article
        glm::vec3 u = tri2 - tri1;
        glm::vec3 v = tri3 - tri1;
    
        glm::vec3 nrmcross = glm::cross(u, v);
        nrmcross = glm::normalize(nrmcross);
        std::cout << "NormalCrs " << nrmcross.x << " " << nrmcross.y << " " << nrmcross.z << "\n";

}

Additional info: The triangle arguments go unchanged as of right now so I can get it working

The first correct call has these vec3s passed in: (0.970976, -0.0246142, -0.0621899) (0.970976, 0.0553858, 0.0178101)' (0.970976, -0.0246142, 0.117237)

The second call which has the last z component correct has these vec3s passed in: (1.93781, 0.0246142, 0.0290235) (2.01781, 0.0553858, 0.0290235) (2.11724, -0.0246142, 0.0290235)

  • 6
    `-4.15243e-08` and `1.82413e-08` are nearly zero, calling that largely inaccurate is probably a bit wrong. – t.niese Sep 14 '20 at 10:52
  • 1
    `-4.15243e-08`. That's the floating point errors which are to be expected. See, e.g., [Is floating point math broked](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – BDL Sep 14 '20 at 10:55
  • Are the argument vectors' values resulting from earlier calculations, that you printed out, or did you input them manually? Did you try to print out the values of vectors `u` and `v`? – Radoslav Voydanovich Sep 14 '20 at 10:59
  • They are resulting from earlier calculations however I have ensured and stepped over ally my code and made sure that these rotated vertices are correct. The values of U and V when printed out for the broken one are "U COMP: 0.08 0.08 -1.86265e-09 V COMP: 0.179427 0 -7.45058e-09" I think it is a floating point error in C++ itself rather than my code. Anyone know how I can fix this? I need this value to be dead accurate as I need a seperating axid to perform seperating axis theorem for collision detection – user324093252 Sep 14 '20 at 11:12
  • What do you mean *largely* inaccurate? -0.00000004 is quite close to 0. – user253751 Sep 14 '20 at 11:23
  • The angle between the correct vector (0,0,-1) and the result is around 0.5 _seconds_... That's not much of a concern IMO – king_nak Sep 14 '20 at 11:31
  • Nevermind about the largely inaccurate I just saw a 4 and thought it was off by a lot more – user324093252 Sep 14 '20 at 11:35

2 Answers2

3

-4.15243e-08 and 1.82413e-08 are nearly zero, calling that largely inaccurate is probably a bit wrong, especially when you take into account that you talk about a vector with the length of 1.

Anyone know how I can fix this?`

You will always have floating-point errors, there is no way around that. sin, tan, cos, pi, … are only approximations, so you always have to expect errors. What you can do is to use glm::dvec3 do use double instead of float, if you need higher accuracy.

Would this affect collision detection or seperating axis theorem at all? I din't realize the values are almost zero. Although they are still not completely accurate I can imagine this wouldn't mess up SAT too much?

Those inaccuracies can accumulate over time, depending on how you use it. E.g. if you have 3 axis and rotate them separately over time. The angle between them can change noticeably. So it always depends on how you use the results if it is a problem or not.

t.niese
  • 39,256
  • 9
  • 74
  • 101
  • If I used this axis to test collisions with separating axis theorem, would I get a lot of false positives or would I not notice a difference? I figure the floating point error is fine as long as it doesn't mess this up. – user324093252 Sep 14 '20 at 11:23
  • Also doubles don't fix the error I just tried. So this isn;t fixable I am assuming? just have to deal with the inaccuracy? – user324093252 Sep 14 '20 at 11:25
  • @user324093252 generally no it should not be a problem. But it depends on how you continue to use the values. That's e.g. the reason why you have a model matrix to that describes the position and orientation of vertexes - that belong together - in the scene, instead of directly translating and rotating the vertexes directly over time. – t.niese Sep 14 '20 at 11:28
  • @user324093252 `Also doubles don't fix the error I just tried.` you can't fix it, you can just increase the accuracy and minimize the error with that. – t.niese Sep 14 '20 at 11:30
1

Single precision floats provide seven significant digits of accuracy (2^-23 relative error). For a vector of length 1, components like 4.10^-8 cannot be distinguished from 0.