计算面法线和缠绕
Computing face normals and winding
给定一个凸多面体,其顶点 (x, y, z) 指定多面体的面。
如何计算多面体每个面的表面法线?
我需要表面法线来计算顶点法线以执行 Gouraud shading。关于如何做到这一点,我能找到的唯一线索是 Newell 的方法,但我如何确保法线是向外法线而不是向内法线?感谢您的帮助。
计算人脸法线
您必须计算跨越包含给定面的平面的两个向量的叉积。它为您提供该面的(非单位)法向量。您必须对其进行归一化,然后就完成了。
如果x0
、x1
、x2
是三角形面的顶点,那么法线可以计算为
vector3 get_normal(vector3 x0, vector3 x1, vector3 x2)
{
vector3 v0 = x0 - x2;
vector3 v1 = x1 - x2;
vector3 n = cross(v0, v1);
return normalize(n);
}
请注意叉积遵循 right-hand rule:
The right-hand rule states that the orientation of the vectors' cross
product is determined by placing u and v tail-to-tail,
flattening the right hand, extending it in the direction of u, and
then curling the fingers in the direction that the angle v makes
with u. The thumb then points in the direction of cross(u, v).
确定三角形的方向
为确保所有法线都指向多面体的 inside/outside,三角形必须统一定向,这意味着所有顶点必须遵循逆时针 (CCW) 或顺时针 (CW)命令。这在计算机图形学中也被称为缠绕。
您可以通过计算下方矩阵的行列式来检查三角形的方向,其中 x3
是第四个点,即您在测试期间的视点。
| x0.x x0.y x0.z 1 |
| x1.x x1.y x1.z 1 |
| x2.x x2.y x2.z 1 |
| x3.x x3.y x3.z 1 |
- 行列式 > 0:
x3
在由逆时针点 { x0, x1, x2 }
定义的平面的 +
侧
- 行列式 < 0:
x3
在逆时针点 { x0, x1, x2 }
定义的平面的 -
侧
- 行列式 = 0:
x3
与 { x0, x1, x2 }
共面
旋转顶点的顺序(通过向左或向右移动所有顶点)不会改变方向。所以 { x0, x1, x2 }
与 { x2, x0, x1 }
和 { x1, x2, x0 }
具有相同的方向。
但是,如果交换两个连续元素的顺序,也会交换到相反的方向。这意味着 { x0, x1, x2 }
与 { x1, x0, x2 }
的方向相反。
使用此信息,您可以轻松地确定三角形的方向:使用谓词矩阵测试每个三角形。如果测试失败,只需交换任意两个连续顶点元素的顺序即可解决问题。
一种简单的方法是首先通过对所有顶点进行平均来计算多面体的(重)中心 C。由于多面体是凸的,因此这将位于其内部。
然后对于每个面通过面的任意两条边的叉积计算法线,然后通过计算法线与V-C的点积来确定法线的方向,其中V是面上的顶点之一;如果此点积为负,则法线是向内的,因此取反(的每个分量)法线以获得向外的法线。
给定一个凸多面体,其顶点 (x, y, z) 指定多面体的面。
如何计算多面体每个面的表面法线?
我需要表面法线来计算顶点法线以执行 Gouraud shading。关于如何做到这一点,我能找到的唯一线索是 Newell 的方法,但我如何确保法线是向外法线而不是向内法线?感谢您的帮助。
计算人脸法线
您必须计算跨越包含给定面的平面的两个向量的叉积。它为您提供该面的(非单位)法向量。您必须对其进行归一化,然后就完成了。
如果x0
、x1
、x2
是三角形面的顶点,那么法线可以计算为
vector3 get_normal(vector3 x0, vector3 x1, vector3 x2)
{
vector3 v0 = x0 - x2;
vector3 v1 = x1 - x2;
vector3 n = cross(v0, v1);
return normalize(n);
}
请注意叉积遵循 right-hand rule:
The right-hand rule states that the orientation of the vectors' cross product is determined by placing u and v tail-to-tail, flattening the right hand, extending it in the direction of u, and then curling the fingers in the direction that the angle v makes with u. The thumb then points in the direction of cross(u, v).
确定三角形的方向
为确保所有法线都指向多面体的 inside/outside,三角形必须统一定向,这意味着所有顶点必须遵循逆时针 (CCW) 或顺时针 (CW)命令。这在计算机图形学中也被称为缠绕。
您可以通过计算下方矩阵的行列式来检查三角形的方向,其中 x3
是第四个点,即您在测试期间的视点。
| x0.x x0.y x0.z 1 |
| x1.x x1.y x1.z 1 |
| x2.x x2.y x2.z 1 |
| x3.x x3.y x3.z 1 |
- 行列式 > 0:
x3
在由逆时针点{ x0, x1, x2 }
定义的平面的 - 行列式 < 0:
x3
在逆时针点{ x0, x1, x2 }
定义的平面的 - 行列式 = 0:
x3
与{ x0, x1, x2 }
共面
+
侧
-
侧
旋转顶点的顺序(通过向左或向右移动所有顶点)不会改变方向。所以 { x0, x1, x2 }
与 { x2, x0, x1 }
和 { x1, x2, x0 }
具有相同的方向。
但是,如果交换两个连续元素的顺序,也会交换到相反的方向。这意味着 { x0, x1, x2 }
与 { x1, x0, x2 }
的方向相反。
使用此信息,您可以轻松地确定三角形的方向:使用谓词矩阵测试每个三角形。如果测试失败,只需交换任意两个连续顶点元素的顺序即可解决问题。
一种简单的方法是首先通过对所有顶点进行平均来计算多面体的(重)中心 C。由于多面体是凸的,因此这将位于其内部。 然后对于每个面通过面的任意两条边的叉积计算法线,然后通过计算法线与V-C的点积来确定法线的方向,其中V是面上的顶点之一;如果此点积为负,则法线是向内的,因此取反(的每个分量)法线以获得向外的法线。