7

Having followed the instructions of the tutorial https://www.youtube.com/watch?v=yc0b5GcYl3U (How To Unwrap A UV Sphere In Blender) I succeeded in generating a textured sphere within the blender program.

Now I want it in my openGL C++ program. To this end I followed the tutorial http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Load_OBJexported in order to save the sphere as an .obj file (using the triangulation export option as stated in said tutorial) and joyfully found a lot of 'v', 'vt', and 'f' lines within the result.

However, parsing the file I found 642 vertices (v), 561 'texture vertices' (vt)[, and 1216 elements lines (f) of the expected structure 'f a/at b/bt c/ct'].

What baffles me is this: My naive understanding of openGL tells me that each point on a textured object has a site in space (the vertex) and a site on the texture (the UV point). Hence I really would expect that the numbers of vs and vts matche. But they do not: 642!=561. How can that be?

Markus-Hermann
  • 789
  • 11
  • 24

2 Answers2

6

Because OBJ and OpenGL use a different definition of "vertex", and handle indices differently.

In the following explanation, I'll call the coordinates of a vertex, which are the values in the v records of the OBJ format, "positions".

OBJ

The main characteristic of the OBJ vertex/index model is that it uses separate indices for different vertex attributes (positions, normals, texture coordinates).

This means that you can have independent lists of positions and texture coordinates, with different sizes. The file only needs to list each unique position once, and each unique texture coordinate pair once.

A vertex is then defined by specifying 3 indices: One each for the position, the texture coordinates, and the normal.

OpenGL

OpenGL on the other hand uses a single set of indices, which reference complete vertices.

A vertex is defined by its position, texture coordinates, and normal. So a vertex is needed for each unique combination of position, texture coordinates, and normal.

Conversion

When you read an OBJ file for OpenGL rendering, you need to create a vertex for each unique combination of position, texture coordinates, and normal. Since they are referenced by indices in the f records, you need to create an OpenGL vertex for each unique index triplet you find in those f records. For each of these vertices, you use the position, texture coordinates, and normals at the given index, as read from the OBJ file.

My older answer here contains pseudo-code to illustrate this process: OpenGL - Index buffers difficulties.

Community
  • 1
  • 1
Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
  • Thanks for your elaborate answer. So I will have to do more than mere parsing but in fact create 3 std::vectors of identical length (being the number of unique corners in the object like e.g. 8 on a cube). Right now I am on my way to bed, but I will think it through tomorrow. – Markus-Hermann Apr 25 '15 at 20:48
  • What I believe to see right away: The indecies given in the 'face' lines do not live in N, but rather in N^2 (or ^3 including normals, which right now I still create in C++) and I best seek out a mapping of this N^2 to N for an openGL Index. e.g. obj (15/13):v15,vt13 -> gl (1):v15,vt13. – Markus-Hermann Apr 25 '15 at 20:58
  • @Markus-Hermann Exactly. That's what I was trying to express by "create an OpenGL vertex for each unique index triplet" in the last paragraph. – Reto Koradi Apr 25 '15 at 21:12
3

A wavefront obj file builds faces (f) by supplying indices to texture coordinates (vt), vertices (v) and normals (vn). If multiple faces share data, they simple use the same index rather than duplicating vt, v or vn data.

Gerard
  • 831
  • 6
  • 15
  • Thanks for your fast reply! I feared something in the lines of "we shun redundancy". This also explains the peculiar form of the 'f'-lines (coming from plain 'f a b c'). Alas, my program does not yet handle this... I guess that will be my todo. – Markus-Hermann Apr 25 '15 at 16:58
  • You'll find that many 3D obj exporters use their own variant. The wavefront obj format is quite lenient by having nearly everything listed as optional. If this is for professional purposes, have a look at _assimp_ for parsing 3D model files. – Gerard Apr 25 '15 at 17:08