0
\$\begingroup\$

I am trying to draw a 3D model from an .obj file, and have met big trouble. I think my model draws with wrong faces, but I can't understand why.

This is what my model looks like.

Original model:

This is original model

This is my code for reading the model:

        using (StreamReader streamReader = new StreamReader("Content/Models/" + path))
        {
            while (!streamReader.EndOfStream)
            {
                List<string> words = new List<string>(streamReader.ReadLine().ToLower().Split(' '));
                words.RemoveAll(s => s == string.Empty);

                if (words.Count == 0)
                    continue;

                string type = words[0];
                words.RemoveAt(0);

                switch (type)
                {
                    // vertex
                    case "v":
                        vertices.Add(new Vector4(float.Parse(words[0], new CultureInfo("en-US").NumberFormat),
                            float.Parse(words[1], new CultureInfo("en-US").NumberFormat),
                            float.Parse(words[2], new CultureInfo("en-US").NumberFormat),
                            words.Count < 4 ? 1 : float.Parse(words[3], new CultureInfo("en-US").NumberFormat)));
                        break;

                    case "vt":
                        textureVertices.Add(new Vector3(float.Parse(words[0], new CultureInfo("en-US").NumberFormat),
                            float.Parse(words[1], new CultureInfo("en-US").NumberFormat),
                            words.Count < 3 ? 0 : float.Parse(words[2], new CultureInfo("en-US").NumberFormat)));
                        break;

                    case "vn":
                        normals.Add(new Vector3(float.Parse(words[0], new CultureInfo("en-US").NumberFormat),
                            float.Parse(words[1], new CultureInfo("en-US").NumberFormat),
                            float.Parse(words[2], new CultureInfo("en-US").NumberFormat)));
                        break;

                    // face
                    case "f":
                        foreach (string w in words)
                        {
                            if (w.Length == 0)
                                continue;

                            string[] comps = w.Split('/');

                            // subtract 1: indices start from 1, not 0
                            vertexIndices.Add(uint.Parse(comps[0]) - 1);

                            if (comps.Length > 1 && comps[1].Length != 0)
                                textureIndices.Add(uint.Parse(comps[1]) - 1);

                            if (comps.Length > 2)
                                normalIndices.Add(uint.Parse(comps[2]) - 1);
                        }
                        break;

                    default:
                        break;
                }
            }
        }

This is code is also available on GitHub - github.com/Freaky-Brainstorm/Deep.

\$\endgroup\$
  • \$\begingroup\$ It also appears you have dumped your code, in case we can identify a problem. Debugging questions must provide a "complete, verifable, minimal example of your code" in order to allow us to recreate the problem. We can not necessarily recreate the problem, because you can not confirm that there is a problem. This also suggests you have not provided minimal code, because quite simply, you could not without absolutely identifying the problem. Perhaps you mean to have your code "peer-reviewed"? If that is the case, you should head to Code Review. \$\endgroup\$ – Gnemlock Sep 16 '16 at 8:36
  • \$\begingroup\$ @Gnemlock I think, I update my question. It's contain minimal code. Just read and draw parts. It's right? \$\endgroup\$ – Aleh Lipka Sep 16 '16 at 9:02
  • \$\begingroup\$ Why do you create so many culturinfo objects? Why do you have a default case if you don't use it? \$\endgroup\$ – Bálint Sep 16 '16 at 9:56
  • \$\begingroup\$ @Bálint Quick fix :) \$\endgroup\$ – Aleh Lipka Sep 16 '16 at 9:57
  • \$\begingroup\$ I think your problem is that you're using separate indices for vertices, texture coordinates and normals, while OpenGL doesn't support that \$\endgroup\$ – Bálint Sep 16 '16 at 9:59
1
\$\begingroup\$

There are better ways than what I show here, but if you're working on a small game (aka.: you're not working on an A++ game) then you'll be fine with this:

The part where you extract the vertex, texture and the normal information from the file is good and should work, but you need to rearrange them so the information for the same vertex should have the same index.

So, I assume you have three lists, vertices for the vertices (obviously) the textureVertices for the UV coords, and the normals for the normals.

The output lists are going to be verts, texs, norms and indices for the vertex positions, UV coords, normals and indices respectively.

vertexIndex := 0
// Processing stuff for the vertices, UV coords and normals
// the "row" string contains the current row
case "f":

   data := split(row, " ")
   // data: ["f", "1/2/3", "4/5/6", "7/8/9"]
   for (i = 1; i <= 3) do
       info := split(data[i], "/")
       // info: ["1", "2", "3"]
       verts.add(vertices[parse(info[0] - 1)])       // Rearrange vertex data
       texs.add(textureVertices[parse(info[1] - 1)])
       norms.add(normals[parse(info[2] - 1)])
       indices.add(vertexIndex)                      // Add the index for the vertex (if you use drawArrays, you can leave out this part)
       vertexIndex = vertexIndex + 1
   end

   break
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.