Search code examples
c++openglglm-mathwavefront

I want to know how to set normals with OBJ loader


Comment part of the presentation code ///// It is an internal code, but I do not know how to set the normal. I created an .obj loader with reference to the reference site, but the lighting is strange as shown in the reference image. What is the cause of this?

what I want to know

How to set the normal of obj file correctly

Current status

The obj file was output in a blender. Direct substitution without using f

reference image: https://i.sstatic.net/K3tcD.jpg

Github : https://github.com/Shigurechan/GL/tree/606cc64088f926d9ba31e09bd2573f43c135bbb0

reference site: http://www.opengl-tutorial.org/jp/beginners-tutorials/tutorial-7-model-loading/

OBJ Loader

// ##################################### .objファイル読み込み #####################################
void FrameWork::D3::LoadObj(const char *fileName, ObjFile &attribute)
{
      ObjFile obj;

      std::vector<int> vertexIndex;
      std::vector<int> uvIndex;
      std::vector<int> normalIndex;

      std::vector<glm::vec3> vertex;
      std::vector<glm::vec2> uv;
      std::vector<glm::vec3> normal;

      FILE *file = fopen(fileName, "r");

      if (file == NULL)
      {
            std::cerr << ".OBJファイルが開けません: " << fileName << std::endl;
            assert(0);
      }
      else
      {
            while (true)
            {
                  char line[500];

                  int res = fscanf(file, "%s", line);

                  if (res == EOF)
                  {
                        break;
                  }

                  if (strcmp(line, "v") == 0)
                  {
                        glm::vec3 vert;
                        fscanf(file, "%f %f %fn", &vert.x, &vert.y, &vert.z);
                        vertex.push_back(vert);
                  }
                  else if (strcmp(line, "vt") == 0)
                  {
                        glm::vec2 u;
                        fscanf(file, "%f %fn", &u.x, &u.y);
                        uv.push_back(u);
                  }
                  else if (strcmp(line, "vn") == 0)
                  {
                        glm::vec3 norm;
                        fscanf(file, "%f %f %fn", &norm.x, &norm.y, &norm.z);
                        normal.push_back(norm);
                  }
                  else if (strcmp(line, "f") == 0)
                  {
                        unsigned int v[3], u[3], n[3];
                        int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%dn", &v[0], &u[0], &n[0], &v[1], &u[1], &n[1], &v[2], &u[2], &n[2]);

                        vertexIndex.push_back(v[0]);
                        vertexIndex.push_back(v[1]);
                        vertexIndex.push_back(v[2]);

                        uvIndex.push_back(u[0]);
                        uvIndex.push_back(u[1]);
                        uvIndex.push_back(u[2]);

                        normalIndex.push_back(n[0]);
                        normalIndex.push_back(n[1]);
                        normalIndex.push_back(n[2]);
                  }
            }
//////////////////////////////////////////////////////////////////
            for (unsigned int i = 0; i < vertexIndex.size(); i++)
            {
                  unsigned int vi = vertexIndex[i];
                  unsigned int ui = uvIndex[i];
                  unsigned int ni = normalIndex[i];

                  glm::vec3 v = vertex[vi - 1];
                  glm::vec2 u = uv[ui - 1];
                  glm::vec3 n = normal[ni - 1];


                  VertexAttribute attrib;

                  attrib.position[0] = v.x;
                  attrib.position[1] = v.y;
                  attrib.position[2] = v.z;

                  attrib.uv[0] = u.x;
                  attrib.uv[1] = u.y;

                  attrib.normal[0] = n.x;
                  attrib.normal[1] = n.y;
                  attrib.normal[2] = n.z;
                  
                  obj.attribute.push_back(attrib);
            }
///////////////////////////////////////////////////////////////////
      }
      attribute = obj;
}


Solution

  • The cause was that I forgot how to specify the front and back of the polygon. The obj loader is correct.

    https://i.sstatic.net/Iq7Ce.jpg

    add code
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);