如果我有一个三角形网格,如何计算每个给定顶点的法线?
我知道如何找到单个三角形的法线。如果我有共享顶点的三角形,我可以通过查找每个三角形各自的法线,对其进行标准化,将其添加到总数中,然后对最终结果进行标准化来部分找到答案。然而,这显然没有考虑到每个法线的适当权重(例如,当与大三角形链接时,许多小三角形可能会偏离答案)。
If I have a mesh of triangles, how does one go about calculating the normals at each given vertex?
I understand how to find the normal of a single triangle. If I have triangles sharing vertices, I can partially find the answer by finding each triangle's respective normal, normalizing it, adding it to the total, and then normalizing the end result. However, this obviously does not take into account proper weighting of each normal (many tiny triangles can throw off the answer when linked with a large triangle, for example).
发布评论
评论(6)
我认为一个好的方法应该是使用加权平均值,但使用角度而不是面积作为权重。在我看来,这是一个更好的答案,因为您正在计算的法线是“局部”特征,因此您并不真正关心贡献的三角形有多大......您需要一种“局部”测量贡献和指定顶点上三角形两侧之间的角度就是这样的局部测量。
使用这种方法,很多小(薄)三角形不会给你一个不平衡的答案。
如果通过使用三角形与以顶点为中心的小球体的交集来本地化计算,则使用角度与使用面积加权平均值相同。
I think a good method should be using a weighted average but using angles instead of area as weights. This is in my opinion a better answer because the normal you are computing is a "local" feature so you don't really care about how big is the triangle that is contributing... you need a sort of "local" measure of the contribution and the angle between the two sides of the triangle on the specified vertex is such a local measure.
Using this approach a lot of small (thin) triangles doesn't give you an unbalanced answer.
Using angles is the same as using an area-weighted average if you localize the computation by using the intersection of the triangles with a small sphere centered in the vertex.
加权平均似乎是最好的方法。
但请注意,根据您的应用,尖角仍然可能会给您带来问题。在这种情况下,您可以通过对叉积小于某个阈值(即更接近平行)的表面法线进行平均来计算多个顶点法线。
使用顶点的多个法向量搜索偏移三角形网格,作者:SJ Kim 等人。等人,了解有关此方法的更多详细信息。
The weighted average appears to be the best approach.
But be aware that, depending on your application, sharp corners could still give you problems. In that case, you can compute multiple vertex normals by averaging surface normals whose cross product is less than some threshold (i.e., closer to being parallel).
Search for Offset triangular mesh using the multiple normal vectors of a vertex by SJ Kim, et. al., for more details about this method.
这篇博文概述了三种不同的方法并给出了一个直观的例子,说明为什么标准和简单的方法(在顶点连接的所有面的法线的面积加权平均值)有时可能会产生较差的结果。
This blog post outlines three different methods and gives a visual example of why the standard and simple method (area weighted average of the normals of all the faces joining at the vertex) might sometimes give poor results.
您可以通过将法线乘以三角形的面积来赋予大三角形更大的权重。
You can give more weight to big triangles by multiplying the normal by the area of the triangle.
查看这篇论文:三角 2 流形的离散微分几何算子。
特别是,“离散平均曲率法线算子”(第 3.5 节,方程 7)给出了独立于曲面细分的稳健法线,这与另一篇 在这里回答。
Check out this paper: Discrete Differential-Geometry Operators for Triangulated 2-Manifolds.
In particular, the "Discrete Mean Curvature Normal Operator" (Section 3.5, Equation 7) gives a robust normal that is independent of tessellation, unlike the methods in the blog post cited by another answer here.
显然,您需要使用加权平均值来获得正确的法线,但是使用三角形面积不会满足您的需要,因为每个三角形的面积与三角形法线代表给定顶点的权重百分比没有关系。
如果您基于进入顶点的两条边之间的角度,您应该为进入顶点的每个三角形获得正确的权重。如果你能以某种方式将其转换为 2d ,这样你就可以离开 360 度的权重基础,这可能会很方便,但很可能只是使用角度本身作为你的权重乘数,在 3d 空间中计算它,然后将所有的相加以这种方式产生的法线并对最终结果进行标准化应该会产生正确的答案。
Obviously you need to use a weighted average to get a correct normal, but using the triangles area won't give you what you need since the area of each triangle has no relationship with the % weight that triangles normal represents for a given vertex.
If you base it on the angle between the two sides coming into the vertex, you should get the correct weight for every triangle coming into it. It might be convenient if you could convert it to 2d somehow so you could go off of a 360 degree base for your weights, but most likely just using the angle itself as your weight multiplier for calculating it in 3d space and then adding up all the normals produced that way and normalizing the final result should produce the correct answer.