std::find 在 glm::vec3 的矢量中不起作用(具有折角的 OpenGL 三角形法线)

std::find in a vector of glm::vec3 is not working (OpenGLTriangle Normals with a crease angle)

我是 OpenGL 和 C++ 的新手,我的代码有问题:

vector<glm::vec3> vTempNormals;
glm::vec3 normal{...};

...
if (angle < glm::radians(creaseAngle))
{
    if (angle != 0.0f)
    {
         if (std::find(vTempNormals.begin(), vTempNormals.end(), normal) == vTempNormals.end())
              vTempNormals.push_back(normal);
    }
}

我试图通过检查 normal 是否已经在向量中然后添加它来避免在我的向量容器中重复 glm::vec3 normal 。但它并不像我期望的那样工作。有时我仍然会重复。我做错了什么?

示例 - 有时有效: angle( 0.19509, 0, 0.980785 ) 和 要检查的法线:

( 0.19509, 0, 0.980785 )
( 0.19509, 0, 0.980785 )
(-0.19509, 0, 0.980785 )
( 0, -1, -0 )
( -0.19509, 0, 0.980785 )
( 0, -1, 0 )
( 0, -1, 0 )

结果:

( -0.19509, 0, 0.980785 )
( 0, -1, -0 )

示例 - 有时它不起作用:angle( 0.19509, 0, 0.980785 ) 和要检查的法线之间:

( 0, 1, 0 )
( 0, 1, 0 )
( 0.555571, 0, 0.831469 )
( 0.19509, 0, 0.980785 )
( 0.19509, 0, 0.980785 )
( 0, 1, 0 )
( 0.555571, -0, 0.831469 )

结果:

( 0, 1, 0 )
( 0.555571, 0, 0.831469 )
( 0, 1, 0 )

您不能仅使用简单的 x == y 表达式来比较浮点值,就好像它们是整数一样。
您必须使用 "threshold""tolerance" 来比较它们,例如类似于:

// Assuming x and y are doubles
if (fabs(x - y) < threshold) {
    // x and y are "near enough", so assume "x == y"
    ...
}

This document,在这种情况下经常被引用,详细介绍了该主题。

如果是矢量,您可以使用差异矢量检查它们是否"almost equal",例如

 // I don't know the details of your glm::vec3 class;
 // anyway, this code assumes that there is a 3D vector class
 // that properly overloads operator-(), returning
 // the vector difference between the two vector operands. 
 Vector3D delta = v2 - v1; 
 if (delta.Length() < threshold)) {
     // ... Assume "v1 == v2"
 }

或者,如果您只是比较 单位向量(就像您问题中的 "normals" 似乎暗示的那样),您可以使用 点积 以更有效地比较它们,检查这些单位向量的方向之间的角度是否为 "small enough"(即小于某个阈值)。

假设您定义了一种比较向量的正确方法,您可以使用 std::find_if()(而不是 std::find())为您提供适当的 lambda自定义比较代码。