以编程方式生成顶点法线


11

我正在使用Kinect面部api,它为三角形提供了一组顶点和索引,这些三角形将被渲染以生成面部图像。

顶点的数目及其在数组中的顺序以及kinect给定的索引始终是恒定的。

但是,该API没有提供有关UV数据和顶点法线的信息。

该应用程序要求我保持kinect给出的顶点顺序,因为它们在3d空间中的位置会根据面部运动而变化,因此在3d编辑软件中生成uv和法线是毫无疑问的。

我设法通过将顶点位置投影到2D平面上来生成UV,因为同一平面上的顶点很少。

但是,我不知道如何为网格生成顶点法线,如果没有顶点法线,则脸部网格的绘制就不会产生任何深度的特征,尽管随着顶点位置的正确,轮廓是可见的。

我了解到,由于缺少顶点法线,因此照明无法在其上正常工作,因此,现在看起来很苍白的无特征网格。

那么当我只有顶点位置和顶点索引以生成三角形时,如何生成顶点法线呢?


n =(v1-v0)x(v2-v0),其中v0,v1和v2是所讨论的(三角形)面的顶点。订单是重要的。如果确实需要,将其标准化。(并且x是叉积)
3Dave

Answers:


14

使用矢量叉积从顶点位置计算法线非常简单。

两个向量和(称为,有时也称为)的叉积是垂直于和的向量,长度为,其中是和之间的夹角。向量的方向取决于乘法的顺序:与相反(两个垂直于平面的方向)。uvu×vuvuv||u×v||=||u||||v||sin(θ)θuvu×vv×u

如果您对十字叉产品不熟悉,我邀请您阅读并熟悉它。这样,法线将看起来很简单。

平面着色法线

如果您有三角形,则是垂直于三角形且长度与面积成比例的向量。由于法线是垂直于三角形平面的单位矢量,因此可以使用以下方法获得法线:ABCAB×AC

N=AB×AC||AB×AC||

在代码中,n = normalize(cross(b-a, c-a))例如。只需将其应用在您的所有脸上,您将获得每张脸的法线。

For each triangle ABC
    n := normalize(cross(B-A, C-A))
    A.n := n
    B.n := n
    C.n := n

请注意,这假设顶点不在三角形之间共享。我对Kinect API不熟悉;它们很可能是共享的,在这种情况下,您将必须复制它们,或者继续进行下一个解决方案:

平滑的阴影法线

用上面计算的法线照明后,您会注意到三角形的边缘是明显的。如果不希望这样做,则可以考虑所有共享同一顶点的面来计算平滑法线。

这个想法是,例如,如果三个三角形,和共享相同的顶点,则法线将是,和的平均值。此外,如果是一个大三角形而是一个微小的三角形,则您可能希望受影响大于受。T 2 T 3 N N 1 N 2 N 3 T 1 T 2 N N 1 N 2T1T2T3NN1N2N3T1T2NN1N2

还记得叉积与面积的比例吗?如果您将叉积相加,然后对总和进行归一化,它将恰好得到我们想要的加权总和。因此该算法变为:

For each vertex
    vertex.n := (0, 0, 0)

For each triangle ABC
    // compute the cross product and add it to each vertex
    p := cross(B-A, C-A)
    A.n += p
    B.n += p
    C.n += p

For each vertex
    vertex.n := normalize(vertex.n)

IñigoQuilez在本文中对此技术进行了更详细的解释:网格的智能归一化


有关法线的更多信息,另请参见:


我将尽快进行并返回结果
Allahjane 16'9

它起作用了感谢一个吨的男人,它确实起作用了,我想要它
Allahjane 16/09/25


@Allahjane:很高兴听到它运行良好。:)
Julien Guertault
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.