Export Blender object to simple file format

Tiny script to export a blender object to a OBJ like of file. This format is very simple to parse. I use this sometimes when working on small simulations where I want to have a 3D model.

import bpy
import math
import mathutils
from mathutils import Vector, Matrix
o = bpy.context.active_object
print("="*40)
output = []
mat_x90 = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
conv_mat = o.matrix_world

def add_vert(face_index, n):
    v = o.data.vertices[face_index].co
    v = conv_mat * v 
    v = mat_x90 * v 
    output.append("v %f %f %f %f %f %f" % (v.x, v.y, v.z, n.x, n.y, n.z))

    
def add_face(face, norm):
    if len(face) == 4:
        add_vert(face[0], norm)
        add_vert(face[1], norm)
        add_vert(face[2], norm)
        add_vert(face[0], norm)
        add_vert(face[2], norm)
        add_vert(face[3], norm)
    elif len(face) == 3:
        add_vert(face[0], norm)
        add_vert(face[1], norm)
        add_vert(face[2], norm)
            
        
for face in o.data.polygons:
    verts = face.vertices[:]
    n = face.normal
    add_face(verts, n)

out_str = "\n".join(map(str, output))

Another example which lets the user select the destination path of the exported file:

import bpy
import math
import mathutils
from mathutils import Vector, Matrix

from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
from bpy.types import Operator


# Get the active object, create rotation matrix for Blender > GL, coordinate system
o = bpy.context.active_object
print("="*40)
output = []
mat_x90 = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
conv_mat = o.matrix_world

# Collect all vertices / normals
def add_vert(face_index, n):
    v = o.data.vertices[face_index].co
    v = conv_mat * v 
    v = mat_x90 * v 
    output.append("v %f %f %f %f %f %f" % (v.x, v.y, v.z, n.x, n.y, n.z))


# Export the given face    
def add_face(face, norm):
    if len(face) == 4:
        add_vert(face[0], norm)
        add_vert(face[1], norm)
        add_vert(face[2], norm)
        add_vert(face[0], norm)
        add_vert(face[2], norm)
        add_vert(face[3], norm)
    elif len(face) == 3:
        add_vert(face[0], norm)
        add_vert(face[1], norm)
        add_vert(face[2], norm)
            

# Called when user selected a file, saved the file
def write_some_data(context, filepath):
    for face in o.data.polygons:
        verts = face.vertices[:]
        n = face.normal
        add_face(verts, n)

    out_str = "\n".join(map(str, output))
    f = open(filepath, 'w', encoding='utf-8')
    f.write(out_str)
    f.close()
    return {'FINISHED'}


# This snippet is necessary to popup the file save window.
# Also adds this operator to the 'space bar menu'
class ExportSomeData(Operator, ExportHelper):
    bl_idname = "export_simple_obj.exp"  
    bl_label = "Export Simple Object (ROXLU)"

    filename_ext = ".txt"
    filter_glob = StringProperty(
            default="*.txt",
            options={'HIDDEN'},
            )
    def execute(self, context):
        return write_some_data(context, self.filepath)


def menu_func_export(self, context):
    self.layout.operator(ExportSomeData.bl_idname, text="Simple Roxlu exporter")

def register():
    bpy.utils.register_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.append(menu_func_export)

def unregister():
    bpy.utils.unregister_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.remove(menu_func_export)


if __name__ == "__main__":
    register()
    bpy.ops.export_simple_obj.exp('INVOKE_DEFAULT')