我正在尝试将模型从 Maya 导出并加载到一个非常简单的 iOS OpenGL ES 设置中。为此,我编写了一个 ruby obj 解析器,它基本上采用顶点和法线并将它们计算成一个我简单地包含的 C 头文件。简单三角单位立方体的输出是以下结构:
Vertex3D cubeVertices[] = {
{{-0.500000f, -0.500000f, 0.500000f},{0.000000f, 0.000000f, 1.000000f},{0.5f, 0.5f, 0.5f, 1},{{0,1,2},{0,6,7},{0,7,1},{0,6,4},{0,4,2}},5},
{{0.500000f, -0.500000f, 0.500000f},{0.000000f, 0.000000f, 1.000000f},{0.5f, 0.5f, 0.5f, 1},{{1,0,2},{1,2,3},{1,0,7},{1,7,3}},4},
{{-0.500000f, 0.500000f, 0.500000f},{0.000000f, 0.000000f, 1.000000f},{0.5f, 0.5f, 0.5f, 1},{{2,0,1},{2,1,3},{2,3,4},{2,4,0}},4},
{{0.500000f, 0.500000f, 0.500000f},{0.000000f, 0.000000f, 1.000000f},{0.5f, 0.5f, 0.5f, 1},{{3,2,1},{3,2,4},{3,4,5},{3,1,7},{3,7,5}},5},
{{-0.500000f, 0.500000f, -0.500000f},{0.000000f, 1.000000f, 0.000000f},{0.5f, 0.5f, 0.5f, 1},{{4,2,3},{4,3,5},{4,5,6},{4,6,0},{4,0,2}},5},
{{0.500000f, 0.500000f, -0.500000f},{0.000000f, 1.000000f, 0.000000f},{0.5f, 0.5f, 0.5f, 1},{{5,4,3},{5,4,6},{5,6,7},{5,3,7}},4},
{{-0.500000f, -0.500000f, -0.500000f},{0.000000f, 1.000000f, 0.000000f},{0.5f, 0.5f, 0.5f, 1},{{6,4,5},{6,5,7},{6,7,0},{6,0,4}},4},
{{0.500000f, -0.500000f, -0.500000f},{0.000000f, 1.000000f, 0.000000f},{0.5f, 0.5f, 0.5f, 1},{{7,6,5},{7,6,0},{7,0,1},{7,1,3},{7,3,5}},5}
};
GLubyte cubeFaceIndices[] = {
0, 1, 2,
2, 1, 3,
2, 3, 4,
4, 3, 5,
4, 5, 6,
6, 5, 7,
6, 7, 0,
0, 7, 1,
1, 7, 3,
3, 7, 5,
6, 0, 4,
4, 0, 2
};
Vertex3D 的定义是
struct Vertex3D {
vec3 position;
vec3 normal;
vec4 color;
Index3D connected_faces[100];
int connectedFaceCount;
};
typedef struct Vertex3D Vertex3D;
现在我需要重新计算我的顶点法线,因为我想要动画一些顶点的运动。为此,我只是将所有连接的顶点索引添加到每个顶点,这就是 connected_faces 索引数组的用途。
对于计算,我只需用叉积计算所有面法线。为此,我只需要使用存储在 Index3D 中的 3 个顶点,加载位置,减去第一个顶点,这样我就有了向量并计算叉积。然后我将属于这个顶点的所有叉积相加,并对向量进行归一化,这是我最终的顶点法线。
我遇到的问题是,碰巧有2个面具有相同的面法线,例如三角立方体总是有2个分割四边形的三角形,该面的法线方向相反。如果我将它们相加,以便稍后计算,它们的总和当然是 Null-Vector。我知道发生这种情况是因为在某些情况下 2 个顶点没有正确的顺序,这意味着 A 应该替换为 B,但我不知道我必须翻转哪个。
有什么数学方法可以估计法线的走向,以及我是计算 AxB 还是 BxA?我在 Maya 中仔细检查了法线,它们在那里非常完美。
编辑:我现在订购了连接的面,效果很好。我正在使用以下方法计算法线:
// every vertex
GLsizei vertexCount = sizeof(cubeVertices) / sizeof(Vertex3D);
for (int i = 0; i < vertexCount; i++) {
vec3 newNormal = {0.0f, 0.0f, 0.0f};
// every vertex connected to the current vertex
GLsizei faceCount = cubeVertices[i].connectedFaceCount;
for(int j = 0; j < faceCount; j++){
Index3D index = cubeVertices[i].connected_faces[j];
vec3 vectorA = cubeVertices[index.a].position;
vec3 vectorB = cubeVertices[index.b].position;
vec3 vectorC = cubeVertices[index.c].position;
vec3 vectorNormal = {0.0f, 0.0f, 0.0f};
substractVectors(&vectorB, &vectorA);
substractVectors(&vectorC, &vectorA);
makeNormal(&vectorB, &vectorC, &vectorNormal);
addVectors(&newNormal, &vectorNormal);
}
// set normal for current vertex
normalize(&newNormal);
cubeVertices[i].normal = newNormal;
}
但是现在我遇到的问题是,通过三角剖分,有时我有 2 条法线指向完全相同的方向,这不会导致我预期的 { 0.33f, 0.33f, 0.33f } 顶点法线。这是正确的行为,还是有其他方法可以计算?
非常感谢您的帮助!