4
$\begingroup$

I would like to export the from Blender calculated vertex normals into an .obj file. I realized that the amount of vertices in the .obj file does not equal the amount of normals (there are more vertices than vn). I expected that there is a vertex normal for each vertex so there should be the same amount of each. I guess Blender doesn't export the vertex normals but the face normals and hence there are less normals than vertices. Did anyone else experience the same problem and solved it somehow? Is there a way to get the vertex normals into the obj file?

$\endgroup$
3
$\begingroup$

Did you check the "Write Normals" option in the export dialog?
The tooltip for that says: "Export one normal per vertex and per face, to represent flat faces and sharp edges"

To test it I edited the vertex normals of a cube with the blend4web add-on and reimported it and the altered normals were preserved on re-import. So with the checkbox checked it should do it the way you want.

EDIT: I looked in the file and I think see what you mean. Let me investigate.
EDIT2: So it seems the vertex normals are only written once, when they are needed (no duplicates) and in the "f-group" they are then referenced. Each face points to its vertex indices and (via the number after the second slash /) to the belonging vertex normal indices (f v//vn - the middle can also have an index for texture coordinate --> f v/vt/vn). So multiple vertices may be associated with the same vertex normal index if they share the same value.

https://en.wikipedia.org/wiki/Wavefront_.obj_file

So in order to have a dictionary (vertex index - vertex normal) you would need to go through the faces (the f-group) and follow the reference for each vertex normal, discarding all vertex indices you already have sampled.

EDIT3: Answering your comment below :)

There are sometimes more 'vn's than 'v's, because there are actually more vertices. One entry in the "v group" doesn't really represent a vertex but a set of unique vertex coordinates.
If you e.g. look at the corner vertex of a cube that is hard-shaded, this one vertex is actually 3 vertices! These 3 share the same coordinates and thus only get one 'v', but they have different normals - one for each face the three-fold corner vertex is part of.

They still can only be moved together - a ripped vertex (meaning two or more unconnected vertices in one place) is represented by having more 'v' entries with the same coordinates. For unripped vertices that are part of a hard edge Blender doesn't show the real count in the scene stats, but if you import it e.g. in Unity the vertex count suddenly is much more.

It looks like that this is just the way that the obj format is designed - not unique identities but just pointers to values. You could of course rewrite the exporter to force duplicates, but it would be difficult to be consistent, because of what I described above. It think would result in all hard edges beeing split. Anyway I think it would be more complicated than just reading out the obj file with some loops and stuff. The information is there, it is just represented differently than we would assume at first glance.

EDIT4: To correct myself above - when reading out the obj it's not really possible to discard any vertices if you want to preserve all info. The combination of v, vn and use in an f is what makes them unique, right? So really you can just walk through the faces and fetch the values. Or gather unique v-vn pairs but lose info about their faces.

$\endgroup$
  • $\begingroup$ Thank you for your investigation! ;) That's what I also figured now that blender does not generate duplicates and just refers to the same vertex normal several times. But maybe there is still a way to force blender to also generate the duplicates since it would make things a lot easier than searching in the texture coordinates for the references. What I also realized at the moment is that for some reason in my obj file there are sometimes even MORE vertex normals given than vertices which does not make any sense to me at all! $\endgroup$ – user29298 Sep 21 '16 at 6:54
  • 1
    $\begingroup$ I updated my answer, because what I wrote was too long for a comment! $\endgroup$ – mbbmbbmm Sep 21 '16 at 13:31
1
$\begingroup$

I modified the default OBJ export script to fix this issue. You can download it from GitHub at Wehrdo/blender-obj-export. After enabling the script and disabling the default exporter, simply check "Write All Normals" on the export options.

The default behavior of reusing vertex normal entries caused issues when trying to do mesh morphing (with SceneKit's SCNMorpher), because multiple exports didn't have a one-to-one correspondence between vertex normals.

$\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.