0

我有一个 obj 文件,它以这种方式存储数据:

v value1 value2 value3  
f value1 value2 value3

首先,我计算面部的法线,然后为该面部的每个顶点分配:

for(int i = 0; i < verticesInd.size(); i+=3)
{
    glm::vec3 normal = glm::normalize(glm::cross(glm::vec3(vertices[verticesInd[i + 1]]) - glm::vec3(vertices[verticesInd[i]]), glm::vec3(vertices[verticesInd[i + 2]]) - glm::vec3(vertices[verticesInd[i]])));
    out_Normals[i] = normal;
    out_Normals[i + 1] = normal;
    out_Normals[i + 2] = normal;
}

为了实现平面着色,我可以复制顶点:

for(int i = 0; i < verticesInd.size(); i++)
{
    out_Vertices.push_back(vertices[verticesInd[i]]);
} 

然后使用 glDrawArrays 绘制对象:

glDrawArrays(GL_TRIANGLES, 0, out_Vertices.size());

为了获得平滑的阴影,我需要平均每个顶点的法线,但我不知道如何找到相邻的面。

Edit1:我没有注意到 f 之前的单个 s 参数:

v value1 value2 value3
s 1  
f value1 value2 value3

Edit2:法线平均

glm::vec3 tNormal;
for(int i = 0; i < vertices.size(); i++)
{
    for(int  j = 0; j < verticesInd.size(); j++)
    {
        if(verticesInd[j] == i)
        {
            tNormal += faceNormals[j / 3];
        }
    }
    aNormals.push_back(glm::normalize(tNormal));
    tNormal = glm::vec3(0,0,0);
}

编辑 3面法线:

for(int i = 0; i < verticesInd.size(); i+=3)
{
    glm::vec3 normal = glm::normalize(glm::cross(glm::vec3(vertices[verticesInd[i + 1]]) - glm::vec3(vertices[verticesInd[i]]), glm::vec3(vertices[verticesInd[i + 2]]) - glm::vec3(vertices[verticesInd[i]])));
    faceNormals.push_back(normal);
}
4

3 回答 3

1

在大多数对象格式中,相邻面应该共享顶点。在顶点处找到平滑的阴影法线应该是一个平均使用该顶点的任何面的法线的问题。

我建议您创建一个与现有顶点数组大小相同的额外新数组。

遍历每个面,并为每个顶点索引,将该顶点的面法线添加到新数组。

在该过程结束时,对结果法线向量进行归一化,然后使用它代替先前计算的面法线。

如果我正确理解您的数据结构,它看起来像这样:

glm::vec3 aNormals[];   // one for each vertex - use the appropriate constructor

for (int i = 0; i < verticesInd.size(); ++i) {
    int f = i / 3;                 // which face is this index part of (3 per face?)
    int v = verticesInd[i];        // which vertex number is being used
    aNormals[v] += faceNormals[f]; // add the face normal to this vertex
}

// now normalise aNormals
于 2012-08-27T17:12:10.007 回答
0

在每个片段照明上关注这个人https://www.youtube.com/watch?v=MRD_zN0SWh0&feature=plcp 。据我所知,它包含相同的方程式,用于在每个顶点的基础上找到法线。

你需要一张面孔列表。如果您曾经见过波前 obj。它们包含多个三角形索引 4,7,2 1,2,3。每 3 个数字代表一张脸。使用普通的 Mesh,每个点只能使用 3 次。如果你找到每个组有一个 3 你可以找到每张脸。找到它们对应的正常值,然后平均。

Alnitak 也有有效的信息。您有一个顶点列表,然后将它们列为 3 个一组,以便您可以将顶点(共享)重用为面部数据。

于 2012-08-27T16:03:21.383 回答
0

我不知道如何找到相邻的面孔。

将面列表添加到临时的 OBJ-loader 顶点存储中。在处理面线时,将新面添加到它引用的每个顶点的面列表中。

这样,您可以在最后旋转所有顶点,查找它所属的面,抓取面法线,然后平均它们。

如果您的 OBJ 没有如此好的内置连接信息(并且没有要求它必须这样做),那么您必须对每个顶点进行最近邻搜索以找到附近的顶点(和相应的面)它。使用您最喜欢的空间索引来加速这些类型的查询。

于 2012-08-27T17:04:15.417 回答