计算每个顶点OpenGL的法线 [英] calculate normal per vertex OpenGL

查看:757
本文介绍了计算每个顶点OpenGL的法线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试计算每个顶点的法线。
但是我做错了。当我运行代码时,我看到:

I am trying the calculate normal per vertex. But I do something wrong. When I run the code I see this:

这里是我的代码,请注意,vertex1是当前顶点之前的顶点,vertex2是当前顶点之后的顶点。

Here Is my code, Note that vertex1 is vertex before the current vertex and vertex2 is vertex after the current vertex.

for (int j = 0; j < meshes[t].face[i].numOfPoints; j++)
            {
                if (normalSetChange)
                {
                    vector3D vertex1, vertex2;

                    if ((j < meshes[t].face[i].numOfPoints - 1) && (j > 0))
                    {
                        vertex1 = vertexes[meshes[t].face[i].vertex[j + 1]] - vertexes[meshes[t].face[i].vertex[j]];
                        vertex2 = vertexes[meshes[t].face[i].vertex[j - 1]] - vertexes[meshes[t].face[i].vertex[j]];
                    }
                    else if (j < meshes[t].face[i].numOfPoints - 1)
                    {
                        vertex1 = vertexes[meshes[t].face[i].vertex[j + 1]] - vertexes[meshes[t].face[i].vertex[j]];
                        vertex2 = vertexes[meshes[t].face[i].vertex[meshes[t].face[i].numOfPoints - 1]] - vertexes[meshes[t].face[i].vertex[j]];
                    }
                    else if (j > 0)
                    {
                        vertex1 = vertexes[meshes[t].face[i].vertex[0]] - vertexes[meshes[t].face[i].vertex[j]];
                        vertex2 = vertexes[meshes[t].face[i].vertex[j - 1]] - vertexes[meshes[t].face[i].vertex[j]];
                    }

                    normalSet = vector3D(vertex1.y * vertex2.z - vertex1.z * vertex2.y,
                                             vertex1.z * vertex2.x - vertex1.x * vertex2.z, 
                                             vertex1.x * vertex2.y - vertex1.y * vertex2.x);

                    normalLength = sqrt(normalSet.x * normalSet.x + normalSet.y * normalSet.y + normalSet.z * normalSet.z);

                    normalSet.x /= normalLength;
                    normalSet.y /= normalLength;
                    normalSet.z /= normalLength;

                    writePolygonLineVCN(PolygonLineVCN(vertexes[meshes[t].face[i].vertex[j]], vertexestexCoordinate[meshes[t].face[i].texCoordinate[j]], normalSet), newFile[workOnCPU]);
                }
                else
                    writePolygonLineVCN(PolygonLineVCN(vertexes[meshes[t].face[i].vertex[j]], vertexestexCoordinate[meshes[t].face[i].texCoordinate[j]], vertexesNormals[meshes[t].face[i].normal[j]]), newFile[workOnCPU]);
            }


推荐答案

,而不是每个顶点。事实上,你可以清楚地看到你贴出的图像中的实体法线。

You are computing normals per triangle, not per vertex. In fact you can clearly see "solid" normals in the image you posted.

为了计算平滑法线,你需要为每个顶点分配一个法线是与该顶点相邻的三角形的法线的平均值。

In order to compute "smooth" normals, you need to assign to each vertex a normal which is an average of the normals of the triangles adjacent to that vertex.

这里是一些伪码,其计算基于两个边缘之间的角度的法线的加权平均值到顶点。 (也许有人使用三角形的面积作为权重,我不知道是否有一个普遍接受的方法来做到这一点)。

Here's some pseudocode, which computed the weighted average of the normals based on the angle between the two edges adjacent to the vertex. (Maybe someone uses the area of the triangle as weight, I don't know if there is an universally accepted way to do it).

vector3D triangleNormalFromVertex(int face_id, int vertex_id) {
   //This assumes that A->B->C is a counter-clockwise ordering
   vector3D A = mesh.face[face_id].vertex[vertex_id];
   vector3D B = mesh.face[face_id].vertex[(vertex_id+1)%3];
   vector3D C = mesh.face[face_id].vertex[(vertex_id+2)%3];


   vector3D N = cross(B-A,C-A);
   float sin_alpha = length(N) / (length(B-A) * length(C-A) );
   return normalize(N) * asin(sin_alpha);
}

void computeNormals() {
    for (vertex v in mesh) {
        vector3D N (0,0,0);
        for (int i = 0;i < NumOfTriangles;++i) {
            if (mesh.face[i].contains(v) ) {
                int VertexID = index_of_v_in_triangle(i,v); //Can be 0,1 or 2
                N = N + triangleNormalFromVertex(i,VertexID);
            }
        }
        N = normalize(N);
        add_N_to_normals_for_vertex_v(N,v);
    }
}

这篇关于计算每个顶点OpenGL的法线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆