Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calculate normal per vertex OpenGL

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

enter image description here

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]);
            }
like image 587
user2320928 Avatar asked Aug 29 '13 19:08

user2320928


People also ask

How is OpenGL normal calculated?

A surface normal for a triangle can be calculated by taking the vector cross product of two edges of that triangle. The order of the vertices used in the calculation will affect the direction of the normal (in or out of the face w.r.t. winding).

How do you find the vertex normal?

The algorithm to compute such vertex normals is as follows: First, allocate an array of normals, one for each vertex in the mesh, and initialize them to zero (Point3( 0,0,0)). Then for each face, compute its face normal, and add it into each of the three vertex normals that the face contributes to.

What is normal OpenGL?

Using vertex normals in OpenGL A normal is an attribute of a vertex, just like its position, its color, its UV coordinates… so just do the usual stuff.

How do you calculate surface normal?

Calculating a surface normal For a plane given by the equation r = a + αb + βc, where a is a vector to get onto the plane and b and c are non-parallel vectors lying on the plane, the normal to the plane defined is given by b × c (the cross product of the vectors lying on the plane).


1 Answers

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);
    }
}
like image 111
sbabbi Avatar answered Sep 30 '22 16:09

sbabbi