Exporting vetex normals and tangents

I’m developing a game using a custom engine, and I’ve been writing an exporter for Blender for my mesh format. I used to only export vertex positions, normals, and uv-coordinates, but I’ve been doing some reading and I learned that tangents are also important for doing correct normal mapping.

Playing around with the API, I noticed that you can’t extract vertex tangent vectors with BMesh, but you can from loops and faces. This is the basis for my script so far:


# Copy and triangulate current object mesh data
mesh = bmesh.new()
mesh.from_mesh(bpy.context.object.data)
bmesh.ops.triangulate(mesh, faces=mesh.faces)
uvLayer = mesh.loops.layers.uv.active

# Create float arrays for outgoing vertex data
positions = array.array('f')
normals = array.array('f')
tangents = array.array('f')
uv0 = array.array('f')

for face in mesh.faces:
    for loop in face.loops:
        # Get position (swizzled)
        positions.append(-loop.vert.co[0])
        positions.append(loop.vert.co[2])
        positions.append(loop.vert.co[1])

        # Get normal (swizzled)
        # TODO: Should this be face, loop, or vertex normal?
        norm = loop.vert.normal
        normals.append(-norm[0])
        normals.append(norm[2])
        normals.append(norm[1])

        # Get tangent (swizzled)
        # TODO: Should this be face or loop tangent?
        tang = loop.calc_tangent()
        tangents.append(-tang[0])
        tangents.append(tang[2])
        tangents.append(tang[1])

        # Get first UV layer
        if uvLayer is not None:
            uv0.append(loop[uvLayer].uv[0])
            uv0.append(loop[uvLayer].uv[1])

mesh.free()

# Write data arrays to a file...

One problem I noticed is that if I use loop or face normals, they’re all directly perpendicular to the face, meaning I don’t get any smooth shading in my game engine. However, it’s not exactly correct to use the normal for the vertex, and the tangent for the face, is it?

On another note, sometimes I do want smooth shading, and other times I don’t. Even if tangents weren’t a question, is there a good way to export normals in such a way that smoothing can be specified per-face, (like when you’re editing a mesh)?

Thanks!