3D表面法线提取器

时间:2009-11-21 23:53:26

标签: 3d extract mesh

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

你能帮帮我吗?

感谢。

理查德

5 个答案:

答案 0 :(得分:3)

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

  1. 我假设您要计算顶点法线,即每个顶点最终会有1个法线
  2. 除了您的65000个顶点位置之外,我还假设您有一些索引列表,用于定义网格中的三角形,例如网格中的三角形1由顶点3,7和3组成。 24.无论你有一个三角形列表或条带或网格面的其他描述,它们基本上都是相同的东西:它们描述了某种确定哪个顶点在特定面中的方法。这些方法之间的区别通常与效率有关,但它并没有真正改变这种算法背后的基本思想。
  3. 您需要做的第一件事是计算网格中每个三角形的法线。对于具有顶点位置矢量a,b和b的三角形。 c,你计算三角形中2个边的边矢量,例如edge1 = b - a,edge2 = c - a。然后,您可以使用这两个向量的叉积来得到此三角形的法线向量。交叉积的结果是一个需要标准化的向量。
  4. 一旦计算了所有三角形法线,通过平均顶点所属的每个三角形的法线来计算顶点的法线。您可以直接执行法线的未加权平均值,即如果顶点是具有法线n1,n2和n的3个面的一部分。 n3,顶点法线简单地为(n1 + n2 + n3)/ 3。您还可以执行加权平均,其中总和中的每个三角形法线都通过某个重要性因子(如该三角形的面积)进行加权。这里没有正确的方法,你可以玩不同的东西。无论哪种方式,一旦计算出平均值,它也需要进行标准化。然而,这可以在1步骤中完成,因为对于3个矢量n1,n2和n。 n3,归一化(n1 + n2 + n3)==归一化((n1 + n2 + n3)/ 3)。
  5. 现在,我必须强调,这是对为了做到这一点需要完成的事情的粗略描述,有些角落可以削减效率。我得到的是你不需要先计算所有三角形法线然后计算所有顶点法线 - 这两个步骤可以混合在一起制作东西更高效。

    某些伪代码可能看起来像

    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();
    }
    

    关于缠绕顺序的其他一些评论 - 如果你弄错了,法线将指向内部,而不是向外。如上所述,只需更改交叉产品的顺序即可解决此问题。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

你需要的只是构成三角形两边的向量的交叉乘积,归一化为单位向量。

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

答案 3 :(得分:0)

我不确定这是否会有所帮助,但请看一下link

答案 4 :(得分:0)

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