Question

I generated model (Suzie) in blender and exported it to .obj file with normals. During loading mode to my app i noticed that numbers of vertices and normals are diffrent (2012 and 1967).

Model details

I try to implement simple cell shading. The problem is in passing normals to shader. For storing vertex data i use vectors from glm.

std::vector<unsigned int> face_indices;
std::vector<unsigned int> normal_indices;
std::vector<glm::vec3> geometry;
std::vector<glm::vec3> normals;

Result i've got so far

Wrong normals

Buffers Layout

    glBindVertexArray(VAO);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
    glBufferData(GL_ARRAY_BUFFER, geometry.size() * sizeof(glm::vec3), &geometry[0], GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, NormalVBOID);
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_DYNAMIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VIndexVBOID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, face_indices.size() * sizeof(unsigned int), &face_indices[0], GL_DYNAMIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

Rendering fragment

    glBindVertexArray(VAO);

    glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);
    glDrawElements(GL_QUADS, face_indices.size(), GL_UNSIGNED_INT, (void*)0);

    glBindVertexArray(0);
Was it helpful?

Solution

The reason that had such wierd problem was that some normals were used more than once to preserve disk space so i had to rearrange them in a proper order. So the solution is pretty trival.

geometry.clear();
normals.clear();

geometry.resize(vv.size());
normals.resize(vv.size());

for (unsigned int i = 0; i < face_indices.size(); i++)
{
    int vi = face_indices[i];
    int ni = normal_indices[i];
    glm::vec3 v = vv [vi];
    glm::vec3 n = vn [ni];
    geometry[vi] = v ;
    normals[vi]  = n ;
    indices.push_back(vi);
}

OTHER TIPS

You should also keep in mind that using the smooth modifier in Blender before export will in some cases help ensure that you have 1 normal per vertex (you may or may not need to also set per-vert normal view instead of face-normal view...can't rem so you'll have to test). This is because by default, blender uses per-face normals. The smooth modifier ("w" hotkey menu) will switch it to per-vertex norms. Then when you export, you export verts and norms as usual, and the number should match. It doesn't always, but this has worked for me in the past. This could possibly mean less unnecessary juggling of your data during import.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top