使用矢量叉积从顶点位置计算法线非常简单。
两个向量和(称为,有时也称为)的叉积是垂直于和的向量,长度为,其中是和之间的夹角。向量的方向取决于乘法的顺序:与相反(两个垂直于平面的方向)。uvu×vu∧vuv||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在本文中对此技术进行了更详细的解释:网格的智能归一化。
有关法线的更多信息,另请参见:
x
是叉积)