0

我有一个具有 3D 65.000 位置坐标的 3D 闭合网格对象。出于照明目的,我需要一个 3D 表面法线提取器。

你能帮我拿下吗。

谢谢。

理查德

4

4 回答 4

3

好的,这是执行此任务的通用算法的尝试,与您使用的语言和图形库无关。

  1. 我将假设您要计算顶点法线,即最终每个顶点有 1 个法线
  2. 除了您的 65000 个顶点位置外,我还假设您有一些索引列表,这些索引定义了网格中的三角形,例如网格中的三角形 1 由顶点 3、7 和 24 组成。无论您有三角形列表还是条形或网格面的其他一些描述,它们基本上都等同于同一件事:它们描述了某种确定哪些顶点在特定面中的方法。这些方法之间的差异通常与效率有关,但并没有真正改变该算法背后的基本思想。
  3. 您需要做的第一件事是计算网格中每个三角形的法线。对于具有顶点位置向量 a、b 和 c 的三角形,计算三角形中 2 个边的边向量,例如 edge1 = b - a, edge2 = c - a。然后你取这两个向量的叉积来得到这个三角形的法线向量。叉积的结果是一个需要归一化的向量。
  4. 计算完所有三角形法线后,通过对顶点所属的每个三角形的法线进行平均来计算顶点的法线。您可以直接对法线进行未加权平均,即如果顶点是法线为 n1、n2 和 n3 的 3 个面的一部分,则顶点法线就是 (n1 + n2 + n3)/3。您还可以进行加权平均,总和中的每个三角形法线都按某个重要因素(例如该三角形的面积)加权。这里没有正确的方法,你可以玩不同的东西。无论哪种方式,一旦计算出平均值,还需要对其进行归一化。然而,这可以在 1 步中完成,因为对于 3 个向量 n1、n2 和 n3,归一化(n1 + n2 + n3)== 归一化((n1 + n2 + n3)/3)。

现在,我必须强调,这是对需要完成的工作的粗略描述,为了提高效率,可以削减某些角落。我要说的是,您不需要先计算所有三角形法线,然后再计算所有顶点法线——这两个步骤可以混合使用以提高效率。

一些伪代码可能看起来像这样

Vector verts[65000];         // 65000 vertex positions
Triangle faces[87000];       // as an example, 87000 triangles
Vector normals[65000];       // 1 normal per vertex - initialised to (0, 0, 0)

// loop over all faces to calculate vertex normals
for (int i=0 ; i<87000 ; i++)
{
    Vector v1 = verts[faces[i].vertex1];
    Vector v2 = verts[faces[i].vertex2];
    Vector v3 = verts[faces[i].vertex3];

    Vector edge1 = v2 - v1;
    Vector edge2 = v3 - v1;
    Vector normal = edge1.CrossProduct(edge2);  // or edge2.CrossProduct(edge1)
    normal.Normalise();

    normals[faces[i].vertex1] += normal;
    normals[faces[i].vertex2] += normal;
    normals[faces[i].vertex3] += normal;
}

// vertex normals need to be normalised
for (int i=0 ; i<65000 ; i++)
{
    normals.Normalise();
}

关于绕线顺序的其他一些评论 - 如果你弄错了,法线将指向内部,而不是向外。如上所述,这可以通过简单地更改叉积的顺序来解决。

于 2009-11-22T00:36:08.703 回答
0

因为你有索引,我假设它是一个三角形列表/条形或扇形。阅读每个三角形。通过取三角形的 2 个向量的叉积来计算法线。你有1个问题。如果您不知道三角形的缠绕顺序,那么您可能会得到相反的值。哪个软件创建了网格?您能否在数据文件或软件中检查缠绕顺序是什么?它是左撇子还是右手?

于 2009-11-22T00:21:44.773 回答
0

您需要的只是构成三角形两侧的向量的叉积,归一化为单位向量。

正如 Andrew Keith 在他的评论中所说,当您从“外部”查看三角形时,您最好知道三角形是顺时针或逆时针定义的。如果你不能保证一致性,你的手就会一团糟。但可能(或至少希望)创建对象的代码是理智的。

于 2009-11-22T00:26:17.807 回答
0

Steg 的回答指向了正确的方向。但是,如果您需要高质量的法线,请查看论文Discrete Differential-Geometry Operators for Triangulated 2-Manifolds。余切公式 (8) 即使对于三角形面积等估计值失效的不规则网格也能提供良好的结果。

于 2009-11-23T01:16:39.870 回答