Beispiel #1
0
    def CreateSegment(self, camera, nameSuffix, length):
        editmode = Window.EditMode()  # are we in edit mode?  If so ...
        if editmode:
            Window.EditMode(0)  # leave edit mode before getting the mesh

        name = camera.getName() + nameSuffix

        # define vertices and faces for a pyramid
        coords = [[-length / 2, 0, 0], [length / 2, 0, 0]]
        edges = [[0, 1]]

        try:
            print "LOOKING FOR MESHDATA"
            me = Mesh.Get(name + 'mesh')
            print dir(me)
        except:
            print "COULD NOT FIND MESH"
            me = Mesh.New(name + 'mesh')

        #print "____ EDGES: ", len(me.edges), "____ VERTS: ", len(me.verts)

        me.verts = None
        me.edges.delete()

        #print "____ EDGES: ", len(me.edges), "____ VERTS: ", len(me.verts)

        me.verts.extend(coords)  # add vertices to mesh
        me.edges.extend(edges)  # add faces to the mesh (also adds edges)

        #print "____ EDGES: ", len(me.edges), "____ VERTS: ", len(me.verts)
        try:
            print "TRYING TO RECOVER OBJECT: "
            ob = Object.Get(name)
            print "++++++ OBJECT RECOVERED: "
        except:
            print "++++++ CREATING NEW OBJECT"
            ob = self.scene.objects.new(me, name)

        if editmode: Window.EditMode(1)  # optional, just being nice

        return ob
Beispiel #2
0
def write(filename, objects,\
EXPORT_NORMALS_HQ=False,\
EXPORT_MTL=True,  EXPORT_COPY_IMAGES=False,\
EXPORT_APPLY_MODIFIERS=True, EXPORT_BLEN_OBS=True,\
EXPORT_GROUP_BY_OB=False):
    '''
    Basic write function. The context and options must be alredy set
    This can be accessed externaly
    eg.
    write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
    '''
    def veckey3d(v):
        return round(v.x, 6), round(v.y, 6), round(v.z, 6)

    def veckey2d(v):
        return round(v.x, 6), round(v.y, 6)

    print 'WTF Export path: "%s"' % filename
    temp_mesh_name = '~tmp-mesh'

    time1 = sys.time()
    scn = Scene.GetCurrent()

    file = open(filename, "w")
    file.write('<?xml version="1.0"?>\n')
    file.write('<OPEN_TRACK>\n')

    # Write Header
    # file.write('\n<!--\n'
    #            + '  Blender3D v%s WTF File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )
    #            + '  www.blender3d.org\n'
    #            + '-->\n\n')

    # Get the container mesh. - used for applying modifiers and non mesh objects.
    containerMesh = meshName = tempMesh = None
    for meshName in Blender.NMesh.GetNames():
        if meshName.startswith(temp_mesh_name):
            tempMesh = Mesh.Get(meshName)
            if not tempMesh.users:
                containerMesh = tempMesh
    if not containerMesh:
        containerMesh = Mesh.New(temp_mesh_name)

    del meshName
    del tempMesh

    # Initialize totals, these are updated each object
    totverts = totuvco = totno = 0

    face_vert_index = 0

    globalNormals = {}

    file.write('\n<library_objects>\n')
    # Get all meshs
    for ob_main in objects:
        obnamestring = fixName(ob_main.name)
        file.write('\t<object id="%s">\n' % obnamestring)  # Write Object name

        for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
            # Will work for non meshes now! :)
            # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None)
            me = BPyMesh.getMeshFromObject(ob, containerMesh,
                                           EXPORT_APPLY_MODIFIERS, False, scn)
            if not me:
                file.write('\t\t<loc>%.6f %.6f %.6f</loc>\n' %
                           tuple(ob_main.loc))  # Write Object name
                file.write('\t\t<rot>%.6f %.6f %.6f</rot>\n' %
                           tuple(ob_main.rot))  # Write Object name
                continue

            faceuv = me.faceUV

            # We have a valid mesh
            if me.faces:
                # Add a dummy object to it.
                has_quads = False
                for f in me.faces:
                    if len(f) == 4:
                        has_quads = True
                        break

                if has_quads:
                    oldmode = Mesh.Mode()
                    Mesh.Mode(Mesh.SelectModes['FACE'])

                    me.sel = True
                    tempob = scn.objects.new(me)
                    me.quadToTriangle(0)  # more=0 shortest length
                    oldmode = Mesh.Mode(oldmode)
                    scn.objects.unlink(tempob)

                    Mesh.Mode(oldmode)

            # Make our own list so it can be sorted to reduce context switching
            faces = [f for f in me.faces]
            edges = me.edges

            if not (len(faces) + len(edges) +
                    len(me.verts)):  # Make sure there is somthing to write
                continue  # dont bother with this mesh.

            me.transform(ob_mat)

            # High Quality Normals
            if faces:
                if EXPORT_NORMALS_HQ:
                    BPyMesh.meshCalcNormals(me)
                else:
                    # transforming normals is incorrect
                    # when the matrix is scaled,
                    # better to recalculate them
                    me.calcNormals()

            # # Crash Blender
            #materials = me.getMaterials(1) # 1 == will return None in the list.
            materials = me.materials

            materialNames = []
            materialItems = materials[:]
            if materials:
                for mat in materials:
                    if mat:  # !=None
                        materialNames.append(mat.name)
                    else:
                        materialNames.append(None)
                # Cant use LC because some materials are None.
                # materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken.

            # Possible there null materials, will mess up indicies
            # but at least it will export, wait until Blender gets fixed.
            materialNames.extend((16 - len(materialNames)) * [None])
            materialItems.extend((16 - len(materialItems)) * [None])

            # Sort by Material, then images
            # so we dont over context switch in the obj file.
            if faceuv:
                try:
                    faces.sort(key=lambda a: (a.mat, a.image, a.smooth))
                except:
                    faces.sort(lambda a, b: cmp((a.mat, a.image, a.smooth),
                                                (b.mat, b.image, b.smooth)))
            elif len(materials) > 1:
                try:
                    faces.sort(key=lambda a: (a.mat, a.smooth))
                except:
                    faces.sort(lambda a, b: cmp((a.mat, a.smooth),
                                                (b.mat, b.smooth)))
            else:
                # no materials
                try:
                    faces.sort(key=lambda a: a.smooth)
                except:
                    faces.sort(lambda a, b: cmp(a.smooth, b.smooth))

            # Set the default mat to no material and no image.
            contextMat = (
                0, 0
            )  # Can never be this, so we will label a new material teh first chance we get.
            contextSmooth = None  # Will either be true or false,  set bad to force initialization switch.

            if len(faces) > 0:
                file.write('\t\t<mesh>\n')
            else:
                file.write('\t\t<curve>\n')

            vertname = "%s-Vertices" % obnamestring
            vertarrayname = "%s-Array" % vertname
            normname = "%s-Normals" % obnamestring
            normarrayname = "%s-Array" % normname
            texname = "%s-TexCoord" % obnamestring
            texarrayname = "%s-Array" % texname

            # Vert
            file.write('\t\t\t<float_array count="%d" id="%s">' %
                       (len(me.verts), vertarrayname))
            for v in me.verts:
                file.write(' %.6f %.6f %.6f' % tuple(v.co))
            file.write('</float_array>\n')
            file.write('\t\t\t<vertices id="%s" source="#%s" />\n' %
                       (vertname, vertarrayname))

            # UV
            if faceuv:
                file.write('\t\t\t<float_array id="%s">' % texarrayname)
                uv_face_mapping = [[0, 0, 0, 0] for f in faces
                                   ]  # a bit of a waste for tri's :/

                uv_dict = {}  # could use a set() here
                for f_index, f in enumerate(faces):

                    for uv_index, uv in enumerate(f.uv):
                        uvkey = veckey2d(uv)
                        try:
                            uv_face_mapping[f_index][uv_index] = uv_dict[uvkey]
                        except:
                            uv_face_mapping[f_index][uv_index] = uv_dict[
                                uvkey] = len(uv_dict)
                            file.write(' %.6f %.6f' % tuple(uv))

                uv_unique_count = len(uv_dict)
                del uv, uvkey, uv_dict, f_index, uv_index
                # Only need uv_unique_count and uv_face_mapping
                file.write('</float_array>\n')
                file.write('\t\t\t<texcoords id="%s" source="#%s" />\n' %
                           (texname, texarrayname))

            # NORMAL, Smooth/Non smoothed.
            if len(faces) > 0:
                file.write('\t\t\t<float_array id="%s">' % normarrayname)
                for f in faces:
                    if f.smooth:
                        for v in f:
                            noKey = veckey3d(v.no)
                            if not globalNormals.has_key(noKey):
                                globalNormals[noKey] = totno
                                totno += 1
                                file.write(' %.6f %.6f %.6f' % noKey)
                    else:
                        # Hard, 1 normal from the face.
                        noKey = veckey3d(f.no)
                        if not globalNormals.has_key(noKey):
                            globalNormals[noKey] = totno
                            totno += 1
                            file.write(' %.6f %.6f %.6f' % noKey)
                file.write('</float_array>\n')
                file.write('\t\t\t<normals id="%s" source="#%s" />\n' %
                           (normname, normarrayname))

            if not faceuv:
                f_image = None
            in_triangles = False

            for f_index, f in enumerate(faces):
                f_v = f.v
                f_smooth = f.smooth
                f_mat = min(f.mat, len(materialNames) - 1)
                if faceuv:
                    f_image = f.image
                    f_uv = f.uv

                # MAKE KEY
                if faceuv and f_image:  # Object is always true.
                    key = materialNames[f_mat], f_image.name
                else:
                    key = materialNames[
                        f_mat], None  # No image, use None instead.

                # CHECK FOR CONTEXT SWITCH
                if key == contextMat:
                    pass  # Context alredy switched, dont do anythoing
                else:
                    if key[0] == None and key[1] == None:
                        # Write a null material, since we know the context has changed.
                        if in_triangles:
                            file.write('</p>\n')
                            file.write('\t\t\t</triangles>\n')
                        file.write('\t\t\t<triangles id="%s_%s">\n' %
                                   (fixName(ob.name), fixName(ob.getData(1))))
                        in_triangles = True
                    else:
                        mat_data = MTL_DICT.get(key)
                        if not mat_data:
                            # First add to global dict so we can export to mtl
                            # Then write mtl

                            # Make a new names from the mat and image name,
                            # converting any spaces to underscores with fixName.

                            # If none image dont bother adding it to the name
                            if key[1] == None:
                                mat_data = MTL_DICT[key] = ('%s' % fixName(
                                    key[0])), materialItems[f_mat], f_image
                            else:
                                mat_data = MTL_DICT[key] = (
                                    '%s_%s' %
                                    (fixName(key[0]), fixName(key[1]))
                                ), materialItems[f_mat], f_image
                        if in_triangles:
                            file.write('</p>\n')
                            file.write('\t\t\t</triangles>\n')
                        file.write(
                            '\t\t\t<triangles id="%s_%s_%s" material="#%s">\n'
                            % (fixName(ob.name), fixName(
                                ob.getData(1)), mat_data[0], mat_data[0]))
                        in_triangles = True

                    file.write(
                        '\t\t\t\t<input offset="0" semantic="VERTEX" source="#%s" />\n'
                        % vertname)
                    file.write(
                        '\t\t\t\t<input offset="1" semantic="NORMAL" source="#%s" />\n'
                        % normname)
                    if faceuv:
                        file.write(
                            '\t\t\t\t<input offset="2" semantic="TEXCOORD" source="#%s" />\n'
                            % texname)
                    file.write('\t\t\t\t<p>')

                contextMat = key
                if f_smooth != contextSmooth:
                    if f_smooth:  # on now off
                        # file.write('s 1\n')
                        contextSmooth = f_smooth
                    else:  # was off now on
                        # file.write('s off\n')
                        contextSmooth = f_smooth

                if faceuv:
                    if f_smooth:  # Smoothed, use vertex normals
                        for vi, v in enumerate(f_v):
                            file.write( ' %d %d %d' % (\
                                v.index+totverts,\
                                totuvco + uv_face_mapping[f_index][vi],\
                                globalNormals[ veckey3d(v.no) ])) # vert, uv, normal

                    else:  # No smoothing, face normals
                        no = globalNormals[veckey3d(f.no)]
                        for vi, v in enumerate(f_v):
                            file.write( ' %d %d %d' % (\
                                v.index+totverts,\
                                totuvco + uv_face_mapping[f_index][vi],\
                                no)) # vert, uv, normal

                    face_vert_index += len(f_v)

                else:  # No UV's
                    if f_smooth:  # Smoothed, use vertex normals
                        for v in f_v:
                            file.write( ' %d %d' % (\
                                v.index+totverts,\
                                globalNormals[ veckey3d(v.no) ]))
                    else:  # No smoothing, face normals
                        no = globalNormals[veckey3d(f.no)]
                        for v in f_v:
                            file.write( ' %d %d' % (\
                                v.index+totverts,\
                                no))
            if in_triangles:
                file.write('</p>\n')
                file.write('\t\t\t</triangles>\n')

            # Write edges.
            LOOSE = Mesh.EdgeFlags.LOOSE
            has_edge = False
            for ed in edges:
                if ed.flag & LOOSE:
                    has_edge = True
            if has_edge:
                file.write('\t\t\t<edges>\n')
                file.write(
                    '\t\t\t\t<input offset="0" semantic="VERTEX" source="#%s" />\n'
                    % vertname)
                file.write('\t\t\t\t<p>')
                for ed in edges:
                    if ed.flag & LOOSE:
                        file.write(
                            ' %d %d' %
                            (ed.v1.index + totverts, ed.v2.index + totverts))
                file.write('</p>\n')
                file.write('\t\t\t</edges>\n')

            # Make the indicies global rather then per mesh
            # totverts += len(me.verts)
            # if faceuv:
            #     totuvco += uv_unique_count
            me.verts = None
            if len(faces) > 0:
                file.write('\t\t</mesh>\n')
            else:
                file.write('\t\t</curve>\n')
        file.write('\t</object>\n')
    file.write('</library_objects>\n\n')

    # Now we have all our materials, save them
    if EXPORT_MTL:
        write_library_materials(file)

    # Save the groups
    write_library_groups(file)

    file.write('</OPEN_TRACK>\n')
    file.close()

    if EXPORT_COPY_IMAGES:
        dest_dir = filename
        # Remove chars until we are just the path.
        while dest_dir and dest_dir[-1] not in '\\/':
            dest_dir = dest_dir[:-1]
        if dest_dir:
            copy_images(dest_dir)
        else:
            print '\tError: "%s" could not be used as a base for an image path.' % filename

    print "WTF Export time: %.2f" % (sys.time() - time1)
Beispiel #3
0
def save_opengl(filename):

    # Open file
    f = open(filename + ".c", "w")
    header_file = open(filename + ".h", "w")
    bone_file = open(filename + ".bone", "w")

    print "File %s created and opened. Now exporting..." % filename

    # Write all the preprocessors in the header file required to
    # make it work w/ vbo_Utilities.h :
    header_file.write("#ifndef MODEL_H")
    header_file.write("\n#define MODEL_H")

    header_file.write("\n\n#include <GL/gl.h>")
    header_file.write("\n#include <GL/glu.h>")
    header_file.write("\n\n#include \"Transformation.h\"")
    header_file.write("\n\n#include \"vbo_Utilities.h\"")
    header_file.write("\n\n#include \"bone.h\"")

    header_file.write(
        "\n\n// The following is the list of objects that will be exported :")
    # The actual object names and their estern declarations will be written out in the loop below

    f.write("#include \"%s.h\"\n\n" % filename)

    # Which object to export
    # currently all objects (meshes only - see below)
    objects = [ob for ob in Object.GetSelected() if ob.getType() == 'Mesh']

    obj_index = 0
    for obj in objects:
        nmesh = NMesh.GetRawFromObject(obj.name)

        header_file.write("\n\nextern CVBO_Model %s;" % (nmesh.name))

        f.write("\n// Object: %s" % (nmesh.name))
        f.write("\nCVBO_Model %s;" % (nmesh.name))
        f.write("\n\nvoid make_%s_vbo_arrays () {" % (nmesh.name))

        # Get the list of vertices for the object
        vertices = nmesh.verts[:]

        # Get the list of faces for the object
        faces = nmesh.faces[:]
        # initialize a refCount array for the vertices
        refCount_for_vertices = []
        for idx in range(len(vertices)):
            refCount_for_vertices.append(0)

        # Make one pass through all the faces in the object
        # to identify all the vertices that will have to be split
        # into 2 or more vertices if they have different texture coordinates
        # as part of different faces. Example : vertices along uv-unwrapping_seams.
        # Naturally, this has to be done only if the mesh uses face-UV textures

        if nmesh.hasFaceUV():
            for face in faces:
                for idx in range(len(face.v)):
                    vertex_idx = face.v[idx].index
                    if refCount_for_vertices[vertex_idx] == 0:
                        refCount_for_vertices[vertex_idx] = 1
                        vertices[vertex_idx].uvco.x = face.uv[idx][0]
                        vertices[vertex_idx].uvco.y = face.uv[idx][1]
                    elif face.uv[idx][0] != vertices[
                            vertex_idx].uvco.x or face.uv[idx][1] != vertices[
                                vertex_idx].uvco.y:
                        # get a new temp vert of type MyVert
                        newVert = MyVert(0.0, 0.0, 0.0)

                        refCount_for_vertices.append(1)

                        # Copy over relevant stuff to newVert
                        newVert.co = Co(vertices[vertex_idx].co.x,
                                        vertices[vertex_idx].co.y,
                                        vertices[vertex_idx].co.z)

                        newVert.index = vertices[vertex_idx].index
                        newVert.dup_vertex_index = vertices[vertex_idx].index

                        newVert.no = No(vertices[vertex_idx].no.x,
                                        vertices[vertex_idx].no.y,
                                        vertices[vertex_idx].no.z)

                        newVert.uvco = Uvco(vertices[vertex_idx].uvco.x,
                                            vertices[vertex_idx].uvco.y)

                        # Append it to the list
                        vertices.append(newVert)

                        vertex_idx = len(
                            vertices
                        ) - 1  # new vertex_idx, of the newly appended vertex

                        # Now set the diverged uvco and index at the newly appended vertex
                        vertices[vertex_idx].uvco.x = face.uv[idx][0]
                        vertices[vertex_idx].uvco.y = face.uv[idx][1]
                        vertices[vertex_idx].index = vertex_idx

                        # And, set the face's v to point to this newly appended vertex
                        face.v[idx] = vertices[vertex_idx]

        numVerts = len(vertices)
        f.write("\n\tint numVertices = %d;\n" % numVerts)

        # Write out the list of vertices for the object
        f.write("\n\t// List of vertices for object %s" % (nmesh.name))
        f.write("\n\tGLfloat vertices[] = {")
        for vertex in vertices:
            f.write("\n\t\t%f,\t%f,\t%f,\t1.0000," %
                    (vertex.co.x, vertex.co.y, vertex.co.z))
            f.write("\t\t// index : %d" % (vertex.index))
        f.write("\n\t};")
        f.write(
            "\n\t%s.bulk_init_vertices (numVertices, (vec4 *)vertices);\n\n" %
            (nmesh.name))

        # Write out the texture coordinates for the object
        if nmesh.hasFaceUV():
            f.write("\n\t// List of texture_coords for object %s" %
                    (nmesh.name))
            f.write("\n\tGLfloat textures[] = {")
            for vertex in vertices:
                f.write("\n\t\t%f,\t%f," % (vertex.uvco.x, vertex.uvco.y))
                f.write("\t\t// index : %d" % (vertex.index))
            f.write("\n\t};")
            f.write(
                "\n\t%s.bulk_init_textures (numVertices, (vec2 *)textures);\n\n"
                % (nmesh.name))

        # Write out the normals for the object
        f.write("\n\t// List of normals for object %s" % (nmesh.name))
        f.write("\n\tGLfloat normals[] = {")
        for vertex in vertices:
            f.write("\n\t\t%f,\t%f,\t%f," %
                    (vertex.no.x, vertex.no.y, vertex.no.z))
            f.write("\t\t// index : %d" % (vertex.index))
        f.write("\n\t};")
        f.write(
            "\n\t%s.bulk_init_normals (numVertices, (vec3 *)normals);\n\n" %
            (nmesh.name))

        numFaces = 0
        for face in nmesh.faces:
            numFaces = numFaces + 1
            if len(
                    face.v
            ) == 4:  # , because quads will be exported as 2 triangles (see below)
                numFaces = numFaces + 1
        f.write("\n\tint numFaces = %d;\n" % numFaces)

        # Write out the indices to form each face of the object
        f.write("\n\tGLuint indices[] = {")
        for face in nmesh.faces:
            f.write("\n\t\t")
            f.write("%d, " % face.v[0].index)
            f.write("%d, " % face.v[1].index)
            f.write("%d, " % face.v[2].index)
            if len(face.v) == 4:
                f.write("\n\t\t")
                f.write("%d, " % face.v[3].index)
                f.write("%d, " % face.v[0].index)
                f.write("%d, " % face.v[2].index)
        f.write("\n\t};")
        f.write("\n\t%s.bulk_init_indices (numFaces, (GLuint *)indices);\n\n" %
                (nmesh.name))

        #translation
        locx = 0
        locy = 0
        locz = 0
        if obj.LocX > 0.0001 or obj.LocX < -0.0001:
            locx = obj.LocX
        if obj.LocY > 0.0001 or obj.LocY < -0.0001:
            locy = obj.LocY
        if obj.LocZ > 0.0001 or obj.LocZ < -0.0001:
            locz = obj.LocZ

        f.write("\n\t%s.locX = %f;" % (nmesh.name, locx))
        f.write("\n\t%s.locY = %f;" % (nmesh.name, locy))
        f.write("\n\t%s.locZ = %f;" % (nmesh.name, locz))

        f.write("\n\treturn;")
        f.write("\n}")

        # Bone stuff

        mesh = Mesh.Get(obj.name)
        obj.link(mesh)
        f.write("\n\n// Object : %s " % (mesh.name))

        numRealVerts = len(mesh.verts)

        armatures = Armature.Get()  # type: dict
        armature_names = armatures.keys()
        for armature_name in armature_names:
            f.write("\n// Armature %s, being used by %d users" %
                    (armature_name, armatures[armature_name].users))
            if armatures[
                    armature_name].users > 0:  # being used by at least 1 user (helps discard deleted armatures which are (for some reason) still lying around in Blender)
                armature = armatures[armature_name]
                bones = armature.bones  # type: dict
                bone_names = bones.keys()
                for bone_name in bone_names:  # loop over all bones
                    bone = bones[bone_name]
                    f.write("\n\nBone %s;" % bone.name)
                    header_file.write("\nextern Bone %s;" % bone.name)

                    f.write("\n\nvoid init_%s_bone_influences () {" %
                            bone.name)
                    f.write("\n\tInfluence influences[] = {")

                    num_influences = 0
                    for vertex_idx in range(
                            numVerts
                    ):  # loop over all vertices, looking for The bone's influences
                        # bone_file.write("\nindex : %d " % (vertex_idx))
                        if vertex_idx < numRealVerts:
                            for influence in mesh.getVertexInfluences(
                                    vertex_idx):
                                if influence[0] == bone.name:
                                    # bone_file.write("\n %s, %f" % (influence[0], influence[1]))
                                    f.write("\n\t\tInfluence(%d, %f)," %
                                            (vertex_idx, influence[1]))
                                    num_influences = num_influences + 1
                        elif vertex_idx >= numRealVerts:
                            for influence in mesh.getVertexInfluences(
                                    vertices[vertex_idx].dup_vertex_index):
                                if influence[0] == bone.name:
                                    # bone_file.write("\n %s, %f" % (influence[0], influence[1]))
                                    f.write("\n\t\tInfluence(%d, %f)," %
                                            (vertex_idx, influence[1]))
                                    num_influences = num_influences + 1

                    f.write("\n\t};")
                    f.write("\n\n\t%s.bulkInitInfluences (%d, influences);" %
                            (bone.name, num_influences))
                    f.write("\n\t%s.name = \"%s\";" % (bone.name, bone.name))
                    f.write("\n\n\treturn;")
                    f.write("\n};\n")

        obj_index += 1

    header_file.write("\n\nvoid initialize_all_models ();")
    header_file.write("\nvoid ready_all_models_for_render ();")

    f.write("\n\nvoid initialize_all_models () {")
    for obj in objects:
        nmesh = NMesh.GetRawFromObject(obj.name)
        f.write("\n\n\tmake_%s_vbo_arrays ();" % (nmesh.name))
        f.write("\n\t%s.setTexture (\"./cube_texture_test.png\", PNG);" %
                nmesh.name)
        f.write("\n\t%s.setMatColor (0.2, 0.3, 0.4, 1.0);" % nmesh.name)
        # Bone stuff :
        armatures = Armature.Get()  # type: dict
        armature_names = armatures.keys()
        for armature_name in armature_names:
            if armatures[
                    armature_name].users > 0:  # being used by at least 1 user (helps discard deleted armatures which are (for some reason) still lying around in Blender)
                armature = armatures[armature_name]
                bones = armature.bones  # type: dict
                bone_names = bones.keys()
                for bone_name in bone_names:  # loop over all bones
                    bone = bones[bone_name]
                    f.write("\n\tinit_%s_bone_influences ();" % bone.name)
                    f.write("\n\t%s.setVBO (&%s);" % (bone.name, obj.name))
                    f.write("\n\t%s.addBone (&%s);" % (obj.name, bone.name))

    f.write("\n\n\treturn;\n}\n")

    f.write("\n\nvoid ready_all_models_for_render () {")
    for obj in objects:
        nmesh = NMesh.GetRawFromObject(obj.name)
        f.write("\n\t%s.make_ready_for_render ();" % nmesh.name)
    f.write("\n\n\treturn;\n}\n\n")

    header_file.write("\n\n#endif\n\n")

    print "Export complete"

    f.close()
Beispiel #4
0
def write(directory, filename, objects):
    def v_n_uv_key(v, n, uv):
        return round(v.x,
                     6), round(v.y, 6), round(v.z, 6), round(n.x, 6), round(
                         n.y, 6), round(n.z, 6), round(uv[0],
                                                       6), round(uv[1], 6)

    def v_n_key(v, n):
        return round(v.x,
                     6), round(v.y,
                               6), round(v.z,
                                         6), round(n.x,
                                                   6), round(n.y,
                                                             6), round(n.z, 6)

    def adjust_key(key, obCenter):
        keyList = list(key)
        keyList[0] -= obCenter[0]
        keyList[1] -= obCenter[1]
        keyList[2] -= obCenter[2]
        return tuple(keyList)

    temp_mesh_name = '~tmp-mesh'

    scn = Scene.GetCurrent()

    # Get the container mesh. - used for applying modifiers and non mesh objects.
    containerMesh = meshName = tempMesh = None
    for meshName in Blender.NMesh.GetNames():
        if meshName.startswith(temp_mesh_name):
            tempMesh = Mesh.Get(meshName)
            if not tempMesh.users:
                containerMesh = tempMesh
    if not containerMesh:
        containerMesh = Mesh.New(temp_mesh_name)

    del meshName
    del tempMesh

    try:
        armature = Blender.Object.Get("Armature")
        write_armature(directory + filename, armature)
    except:
        armature = None

# Get all meshs
    for ob_main in objects:
        for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
            me = BPyMesh.getMeshFromObject(ob, containerMesh, True, False, scn)
            if not me:
                continue

            # Initialize globalVertices and globalMaterials dictionaries
            vertIndex = 0
            matIndex = 0
            globalVertices = {}
            globalMaterials = {}
            # Dictionary of materials: (material.name, image.name):matname_imagename
            # matname_imagename has fixed names.
            materialDict = {}

            # We have a valid mesh
            if me.faces:
                # Add a dummy object to it.
                has_quads = False
                for f in me.faces:
                    if len(f) == 4:
                        has_quads = True
                        break

                if has_quads:
                    oldmode = Mesh.Mode()
                    Mesh.Mode(Mesh.SelectModes['FACE'])

                    me.sel = True
                    tempob = scn.objects.new(me)
                    me.quadToTriangle(0)  # more=0 shortest length
                    oldmode = Mesh.Mode(oldmode)
                    scn.objects.unlink(tempob)

                    Mesh.Mode(oldmode)
            else:
                continue

            # High Quality Normals
            BPyMesh.meshCalcNormals(me)

            # Make our own list so it can be sorted to reduce context switching
            faces = [f for f in me.faces]
            faceuv = me.faceUV
            edges = me.edges

            materials = me.materials
            materialNames = []
            materialItems = materials[:]
            if materials:
                for mat in materials:
                    if mat:
                        materialNames.append(mat.name)
                    else:
                        materialNames.append(None)

            # Possible there null materials, will mess up indicies
            # but at least it will export, wait until Blender gets fixed.
            materialNames.extend((16 - len(materialNames)) * [None])
            materialItems.extend((16 - len(materialItems)) * [None])

            # Sort by Material, then images
            # so we dont over context switch in the obj file.
            if faceuv:
                try:
                    faces.sort(key=lambda a: (a.mat, a.image, a.smooth))
                except:
                    faces.sort(lambda a, b: cmp((a.mat, a.image, a.smooth),
                                                (b.mat, b.image, b.smooth)))
            elif len(materials) > 1:
                try:
                    faces.sort(key=lambda a: (a.mat, a.smooth))
                except:
                    faces.sort(lambda a, b: cmp((a.mat, a.smooth),
                                                (b.mat, b.smooth)))
            else:  # no materials
                try:
                    faces.sort(key=lambda a: a.smooth)
                except:
                    faces.sort(lambda a, b: cmp(a.smooth, b.smooth))

            # Set the default mat to no material and no image.
            contextMat = (
                0, 0
            )  # Can never be this, so we will label a new material the first chance we get.
            contextSmooth = None  # Will either be true or false,  set bad to force initialization switch.

            name1 = ob.name
            name2 = ob.getData(1)
            obnamestring = fixName(name1)
            file = open(directory + obnamestring + ".drkMesh", "w")

            # Fill globalVertices dictionary by creating (vert, normal, uv) tuple for all vertices of all faces
            vertString = ""
            obCenter = ob.getLocation()
            if faceuv:
                vOutputFormat = 'v %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f\n'
            else:
                vOutputFormat = 'v %.6f %.6f %.6f %.6f %.6f %.6f\n'
                f_image = None

            #Loop through all faces
            submeshCount = 0
            faceCount = 0
            faceCounts = []
            for face in faces:
                if faceuv:
                    faceUVs = list(face.uv)
                faceUVindex = 0
                faceIndices = []
                for v in face:
                    if face.smooth:
                        vno = v.no
                    else:
                        vno = face.no
                    if faceuv:
                        key = v_n_uv_key(v.co, v.no, faceUVs[faceUVindex])
                        faceUVindex += 1
                    else:
                        key = v_n_key(v.co, v.no)
                    if not globalVertices.has_key(key):
                        globalVertices[key] = vertIndex
                        vertString += vOutputFormat % key
                        faceIndices.append(vertIndex)
                        vertIndex += 1
                    else:
                        faceIndices.append(globalVertices[key])

                # Make material,texture key
                f_mat = min(face.mat, len(materialNames) - 1)
                if faceuv:
                    f_image = face.image
                if faceuv and f_image:
                    matKey = materialNames[f_mat], f_image.name
                else:
                    matKey = materialNames[f_mat], None

            # Check for context switch
                if matKey != contextMat:
                    submeshCount += 1
                    if matKey[0] == None and matKey[1] == None:
                        # Write a null material, since we know the context has changed.
                        faceString += 'use (null)\n'  # mat, image

                    else:
                        mat_data = materialDict.get(matKey)
                        if not mat_data:
                            mat_data = materialDict[matKey] = fixName(
                                matKey[0]), materialItems[f_mat], f_image

                        vertString += 'use %d\n' % matIndex
                        globalMaterials[mat_data[0]] = matIndex
                        matIndex += 1
                    if faceCount != 0:
                        faceCounts.append(faceCount)
                        faceCount = 0

                contextMat = matKey
                vertString += 'face %d %d %d\n' % tuple(faceIndices)
                faceCount += 1
            faceCounts.append(faceCount)
            file.write('count %d\n' % vertIndex)
            if faceuv:
                file.write('uvs\n')
            file.write('submeshes %d\n' % submeshCount)
            for faceCount in faceCounts:
                file.write('faces %d\n' % faceCount)
            file.write(vertString)

            me.verts = None
            write_mtl(file, materialDict, globalMaterials)
            file.close()
Beispiel #5
0
def write(filename, objects,\
EXPORT_TRI=False,  EXPORT_EDGES=False,  EXPORT_NORMALS=False,  EXPORT_NORMALS_HQ=False,\
EXPORT_UV=True,  EXPORT_MTL=True,  EXPORT_COPY_IMAGES=False,\
EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\
EXPORT_GROUP_BY_OB=False,  EXPORT_GROUP_BY_MAT=False, EXPORT_MORPH_TARGET=False, EXPORT_ARMATURE=False):
	'''
	Basic write function. The context and options must be alredy set
	This can be accessed externaly
	eg.
	write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
	'''
	
	def veckey3d(v):
		return round(v.x, 6), round(v.y, 6), round(v.z, 6)
		
	def veckey2d(v):
		return round(v.x, 6), round(v.y, 6)
	
	print 'OBJ Export path: "%s"' % filename
	temp_mesh_name = '~tmp-mesh'

	time1 = sys.time()
	scn = Scene.GetCurrent()

	file = open(filename, "w")
	
	# Write Header
	file.write('# Blender3D v%s OBJ File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ))
	file.write('# www.blender3d.org\n')

	# Tell the obj file what material file to use.
	if EXPORT_MTL:
		mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1])
		file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] ))
	
	# Get the container mesh. - used for applying modifiers and non mesh objects.
	containerMesh = meshName = tempMesh = None
	for meshName in Blender.NMesh.GetNames():
		if meshName.startswith(temp_mesh_name):
			tempMesh = Mesh.Get(meshName)
			if not tempMesh.users:
				containerMesh = tempMesh
	if not containerMesh:
		containerMesh = Mesh.New(temp_mesh_name)
	
	if EXPORT_ROTX90:
		mat_xrot90= Blender.Mathutils.RotationMatrix(-90, 4, 'x')
		
	del meshName
	del tempMesh
	
	# Initialize totals, these are updated each object
	totverts = totuvco = totno = 1
	
	face_vert_index = 1
	
	globalNormals = {}
	
	# Get all meshs
	for ob_main in objects:
		for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
			# Will work for non meshes now! :)
			# getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None)
                        if EXPORT_ARMATURE:
				write_armature(file,ob)
				write_poses(file,ob)
			me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn)
			if not me:
				continue
			
			if EXPORT_UV:
				faceuv= me.faceUV
			else:
				faceuv = False
			
			# We have a valid mesh
			if EXPORT_TRI and me.faces:
				# Add a dummy object to it.
				has_quads = False
				for f in me.faces:
					if len(f) == 4:
						has_quads = True
						break
				
				if has_quads:
					oldmode = Mesh.Mode()
					Mesh.Mode(Mesh.SelectModes['FACE'])
					
					me.sel = True
					tempob = scn.objects.new(me)
					me.quadToTriangle(0) # more=0 shortest length
					oldmode = Mesh.Mode(oldmode)
					scn.objects.unlink(tempob)
					
					Mesh.Mode(oldmode)
			

			faces = [ f for f in me.faces ]
			
			if EXPORT_EDGES:
				edges = me.edges
			else:
				edges = []
			
			if not (len(faces)+len(edges)+len(me.verts)): # Make sure there is somthing to write
				continue # dont bother with this mesh.
			
			if EXPORT_ROTX90:
                                me.transform(ob_mat*mat_xrot90)
			else:
				me.transform(ob_mat)
			
			# High Quality Normals
			if EXPORT_NORMALS and faces:
				if EXPORT_NORMALS_HQ:
					BPyMesh.meshCalcNormals(me)
				else:
					# transforming normals is incorrect
					# when the matrix is scaled,
					# better to recalculate them
					me.calcNormals()
			
			# # Crash Blender
			#materials = me.getMaterials(1) # 1 == will return None in the list.
			materials = me.materials
			
			materialNames = []
			materialItems = materials[:]
			if materials:
				for mat in materials:
					if mat: # !=None
						materialNames.append(mat.name)
					else:
						materialNames.append(None)
				# Cant use LC because some materials are None.
				# materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken.  
			
			# Possible there null materials, will mess up indicies
			# but at least it will export, wait until Blender gets fixed.
			materialNames.extend((16-len(materialNames)) * [None])
			materialItems.extend((16-len(materialItems)) * [None])
			
			# Sort by Material, then images
			# so we dont over context switch in the obj file.
			if EXPORT_MORPH_TARGET:
				pass
			elif faceuv:
				try:	faces.sort(key = lambda a: (a.mat, a.image, a.smooth))
				except: faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth)))
			elif len(materials) > 1:
				try:	faces.sort(key = lambda a: (a.mat, a.smooth))
				except: faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth)))
			else:
				# no materials
				try:	faces.sort(key = lambda a: a.smooth)
				except: faces.sort(lambda a,b: cmp(a.smooth, b.smooth))
			
			# Set the default mat to no material and no image.
			contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get.
			contextSmooth = None # Will either be true or false,  set bad to force initialization switch.
			
			if EXPORT_BLEN_OBS or EXPORT_GROUP_BY_OB:
				name1 = ob.name
				name2 = ob.getData(1)
				if name1 == name2:
					obnamestring = fixName(name1)
				else:
					obnamestring = '%s_%s' % (fixName(name1), fixName(name2))
				
				if EXPORT_BLEN_OBS:
					file.write('o %s\n' % obnamestring) # Write Object name
				else: # if EXPORT_GROUP_BY_OB:
					file.write('g %s\n' % obnamestring)
			
			
			
			# Vert
			mesh = ob.getData()
                        objmat = ob.getMatrix()
                        for i in objmat:
		          file.write('obm: %.6f %.6f %.6f %.6f\n' % tuple(i))
			vgrouplist = mesh.getVertGroupNames()
			file.write('vgroupcount: %i\n' % len(vgrouplist))
			for vgname in vgrouplist:
				file.write('vgroup: %s\n' % vgname)
			for v in mesh.verts:
				file.write('v %.6f %.6f %.6f\n' % tuple(v.co))
				influences = mesh.getVertexInfluences(v.index)
				file.write('influence: %i\n' % len(influences))
				for name,weight in influences:
					file.write('GroupName: %s\n' % name)
					file.write('Weight: %f\n' % weight)
			
			# UV
			if faceuv:
				uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/
				
				uv_dict = {} # could use a set() here
				for f_index, f in enumerate(faces):
					
					for uv_index, uv in enumerate(f.uv):
						uvkey = veckey2d(uv)
						try:
							uv_face_mapping[f_index][uv_index] = uv_dict[uvkey]
						except:
							uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict)
							file.write('vt %.6f %.6f\n' % tuple(uv))
				
				uv_unique_count = len(uv_dict)
				del uv, uvkey, uv_dict, f_index, uv_index
				# Only need uv_unique_count and uv_face_mapping
			
			# NORMAL, Smooth/Non smoothed.
			if EXPORT_NORMALS:
				for f in faces:
					if f.smooth:
						for v in f:
							noKey = veckey3d(v.no)
							if not globalNormals.has_key( noKey ):
								globalNormals[noKey] = totno
								totno +=1
								file.write('vn %.6f %.6f %.6f\n' % noKey)
					else:
						# Hard, 1 normal from the face.
						noKey = veckey3d(f.no)
						if not globalNormals.has_key( noKey ):
							globalNormals[noKey] = totno
							totno +=1
							file.write('vn %.6f %.6f %.6f\n' % noKey)
			
			if not faceuv:
				f_image = None
			
			for f_index, f in enumerate(faces):
				f_v= f.v
				f_smooth= f.smooth
				f_mat = min(f.mat, len(materialNames)-1)
				if faceuv:
					f_image = f.image
					f_uv= f.uv
				
				# MAKE KEY
				if faceuv and f_image: # Object is always true.
					key = materialNames[f_mat],  f_image.name
				else:
					key = materialNames[f_mat],  None # No image, use None instead.
				
				# CHECK FOR CONTEXT SWITCH
				if key == contextMat:
					pass # Context alredy switched, dont do anythoing
				else:
					if key[0] == None and key[1] == None:
						# Write a null material, since we know the context has changed.
						if EXPORT_GROUP_BY_MAT:
							file.write('g %s_%s\n' % (fixName(ob.name), fixName(ob.getData(1))) ) # can be mat_image or (null)
						file.write('usemtl (null)\n') # mat, image
						
					else:
						mat_data= MTL_DICT.get(key)
						if not mat_data:
							# First add to global dict so we can export to mtl
							# Then write mtl
							
							# Make a new names from the mat and image name,
							# converting any spaces to underscores with fixName.
							
							# If none image dont bother adding it to the name
							if key[1] == None:
								mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image
							else:
								mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image
						
						if EXPORT_GROUP_BY_MAT:
							file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null)
						file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null)
					
				contextMat = key
				if f_smooth != contextSmooth:
					if f_smooth: # on now off
						file.write('s 1\n')
						contextSmooth = f_smooth
					else: # was off now on
						file.write('s off\n')
						contextSmooth = f_smooth
				
				file.write('f')
				if faceuv:
					if EXPORT_NORMALS:
						if f_smooth: # Smoothed, use vertex normals
							for vi, v in enumerate(f_v):
								file.write( ' %d/%d/%d' % (\
								  v.index+totverts,\
								  totuvco + uv_face_mapping[f_index][vi],\
								  globalNormals[ veckey3d(v.no) ])) # vert, uv, normal
							
						else: # No smoothing, face normals
							no = globalNormals[ veckey3d(f.no) ]
							for vi, v in enumerate(f_v):
								file.write( ' %d/%d/%d' % (\
								  v.index+totverts,\
								  totuvco + uv_face_mapping[f_index][vi],\
								  no)) # vert, uv, normal
					
					else: # No Normals
						for vi, v in enumerate(f_v):
							file.write( ' %d/%d' % (\
							  v.index+totverts,\
							  totuvco + uv_face_mapping[f_index][vi])) # vert, uv
					
					face_vert_index += len(f_v)
				
				else: # No UV's
					if EXPORT_NORMALS:
						if f_smooth: # Smoothed, use vertex normals
							for v in f_v:
								file.write( ' %d//%d' % (\
								  v.index+totverts,\
								  globalNormals[ veckey3d(v.no) ]))
						else: # No smoothing, face normals
							no = globalNormals[ veckey3d(f.no) ]
							for v in f_v:
								file.write( ' %d//%d' % (\
								  v.index+totverts,\
								  no))
					else: # No Normals
						for v in f_v:
							file.write( ' %d' % (\
							  v.index+totverts))
						
				file.write('\n')
			
			# Write edges.
			if EXPORT_EDGES:
				LOOSE= Mesh.EdgeFlags.LOOSE
				for ed in edges:
					if ed.flag & LOOSE:
						file.write('f %d %d\n' % (ed.v1.index+totverts, ed.v2.index+totverts))
				
			# Make the indicies global rather then per mesh
			totverts += len(me.verts)
			if faceuv:
				totuvco += uv_unique_count
			me.verts= None
	file.close()
	
	
	# Now we have all our materials, save them
	if EXPORT_MTL:
		write_mtl(mtlfilename)
	if EXPORT_COPY_IMAGES:
		dest_dir = filename
		# Remove chars until we are just the path.
		while dest_dir and dest_dir[-1] not in '\\/':
			dest_dir = dest_dir[:-1]
		if dest_dir:
			copy_images(dest_dir)
		else:
			print '\tError: "%s" could not be used as a base for an image path.' % filename
	
	print "OBJ Export time: %.2f" % (sys.time() - time1)
Beispiel #6
0
    def export(self, scene, world, alltextures,\
      EXPORT_APPLY_MODIFIERS = False,\
      EXPORT_TRI=    False,\
     ):

        print "Info: starting X3D export to " + self.filename + "..."
        self.writeHeader()
        # self.writeScript()
        self.writeNavigationInfo(scene)
        self.writeBackground(world, alltextures)
        self.writeFog(world)
        self.proto = 0

        # COPIED FROM OBJ EXPORTER
        if EXPORT_APPLY_MODIFIERS:
            temp_mesh_name = '~tmp-mesh'

            # Get the container mesh. - used for applying modifiers and non mesh objects.
            containerMesh = meshName = tempMesh = None
            for meshName in Blender.NMesh.GetNames():
                if meshName.startswith(temp_mesh_name):
                    tempMesh = Mesh.Get(meshName)
                    if not tempMesh.users:
                        containerMesh = tempMesh
            if not containerMesh:
                containerMesh = Mesh.New(temp_mesh_name)
        # --------------------------

        for ob_main in scene.objects.context:
            for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
                objType = ob.type
                objName = ob.name
                self.matonly = 0
                if objType == "Camera":
                    self.writeViewpoint(ob, ob_mat, scene)
                elif objType in ("Mesh", "Curve", "Surf", "Text"):
                    if EXPORT_APPLY_MODIFIERS or objType != 'Mesh':
                        me = BPyMesh.getMeshFromObject(ob, containerMesh,
                                                       EXPORT_APPLY_MODIFIERS,
                                                       False, scene)
                    else:
                        me = ob.getData(mesh=1)

                    self.writeIndexedFaceSet(ob,
                                             me,
                                             ob_mat,
                                             world,
                                             EXPORT_TRI=EXPORT_TRI)
                elif objType == "Lamp":
                    data = ob.data
                    datatype = data.type
                    if datatype == Lamp.Types.Lamp:
                        self.writePointLight(ob, ob_mat, data, world)
                    elif datatype == Lamp.Types.Spot:
                        self.writeSpotLight(ob, ob_mat, data, world)
                    elif datatype == Lamp.Types.Sun:
                        self.writeDirectionalLight(ob, ob_mat, data, world)
                    else:
                        self.writeDirectionalLight(ob, ob_mat, data, world)
                # do you think x3d could document what to do with dummy objects?
                #elif objType == "Empty" and objName != "Empty":
                #	self.writeNode(ob, ob_mat)
                else:
                    #print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType)
                    pass

        self.file.write("\n</Scene>\n</X3D>")

        if EXPORT_APPLY_MODIFIERS:
            if containerMesh:
                containerMesh.verts = None

        self.cleanup()
Beispiel #7
0
def write(filename, objects,\
EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True):
    '''
	Basic write function. The context and options must be alredy set
	This can be accessed externaly
	eg.
	write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
	'''
    def veckey3d(v):
        return round(v.x, 6), round(v.y, 6), round(v.z, 6)

    def veckey2d(v):
        return round(v.x, 6), round(v.y, 6)

    print 'EOL MESH Export path: "%s"' % filename
    temp_mesh_name = '~tmp-mesh'
    time1 = sys.time()
    scn = Scene.GetCurrent()
    file = open(filename, "w")

    # Write Header
    file.write('# Blender3D v%s EOL MESH File: %s\n' %
               (Blender.Get('version'),
                Blender.Get('filename').split('/')[-1].split('\\')[-1]))
    file.write('# www.blender3d.org\n')

    # Get the container mesh. - used for applying modifiers and non mesh objects.
    containerMesh = meshName = tempMesh = None
    for meshName in Blender.NMesh.GetNames():
        if meshName.startswith(temp_mesh_name):
            tempMesh = Mesh.Get(meshName)
            if not tempMesh.users:
                containerMesh = tempMesh
    if not containerMesh:
        containerMesh = Mesh.New(temp_mesh_name)

    if EXPORT_ROTX90:
        mat_xrot90 = Blender.Mathutils.RotationMatrix(-90, 4, 'x')

    del meshName
    del tempMesh

    # Initialize totals, these are updated each object
    totverts = totuvco = totno = 1

    face_vert_index = 1

    globalNormals = {}

    # Get all meshs
    for ob_main in objects:
        for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
            # Will work for non meshes now! :)
            # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None)
            me = BPyMesh.getMeshFromObject(ob, containerMesh,
                                           EXPORT_APPLY_MODIFIERS, False, scn)
            if not me:
                continue

            faceuv = me.faceUV
            has_quads = False
            for f in me.faces:
                if len(f) == 4:
                    has_quads = True
                    break
            if has_quads:
                oldmode = Mesh.Mode()
                Mesh.Mode(Mesh.SelectModes['FACE'])
                me.sel = True
                tempob = scn.objects.new(me)
                me.quadToTriangle(0)  # more=0 shortest length
                oldmode = Mesh.Mode(oldmode)
                scn.objects.unlink(tempob)
                Mesh.Mode(oldmode)
            edges = me.edges

            faces = [f for f in me.faces]
            if EXPORT_ROTX90:
                me.transform(ob_mat * mat_xrot90)
            else:
                me.transform(ob_mat)

            # Vert
            mesh = ob.getData()
            objmat = ob.getMatrix()
            for i in objmat:
                file.write('obm: %.6f %.6f %.6f %.6f\n' % tuple(i))
            vgrouplist = mesh.getVertGroupNames()
            file.write('vgroupcount: %i\n' % len(vgrouplist))
            for vgname in vgrouplist:
                file.write('vgroup: %s\n' % vgname)
            file.write('vertexcount: %i\n' % len(mesh.verts))
            for v in mesh.verts:
                file.write('v %.6f %.6f %.6f\n' % tuple(v.co))
                influences = mesh.getVertexInfluences(v.index)
                file.write('influence: %i\n' % len(influences))
                for name, weight in influences:
                    file.write('groupname: %s\n' % name)
                    file.write('weight: %f\n' % weight)

            # UV
            if faceuv:
                uv_face_mapping = [[0, 0, 0, 0] for f in faces
                                   ]  # a bit of a waste for tri's :/

                uv_dict = {}  # could use a set() here
                for f_index, f in enumerate(faces):

                    for uv_index, uv in enumerate(f.uv):
                        uvkey = veckey2d(uv)
                        try:
                            uv_face_mapping[f_index][uv_index] = uv_dict[uvkey]
                        except:
                            uv_face_mapping[f_index][uv_index] = uv_dict[
                                uvkey] = len(uv_dict)
                            file.write('vt %.6f %.6f\n' % tuple(uv))

                uv_unique_count = len(uv_dict)
                del uv, uvkey, uv_dict, f_index, uv_index
                # Only need uv_unique_count and uv_face_mapping
                file.write('uvcount: %i\n' % uv_unique_count)
            # NORMAL, Smooth/Non smoothed.
            for f in faces:
                if f.smooth:
                    for v in f:
                        noKey = veckey3d(v.no)
                        if not globalNormals.has_key(noKey):
                            globalNormals[noKey] = totno
                            totno += 1
                            file.write('vn %.6f %.6f %.6f\n' % noKey)
                else:
                    # Hard, 1 normal from the face.
                    noKey = veckey3d(f.no)
                    if not globalNormals.has_key(noKey):
                        globalNormals[noKey] = totno
                        totno += 1
                        file.write('vn %.6f %.6f %.6f\n' % noKey)
            file.write('normalcount: %i\n' % len(globalNormals))

            if not faceuv:
                f_image = None

            file.write('facecount: %i\n' % len(faces))
            for f_index, f in enumerate(faces):
                f_v = f.v
                f_smooth = f.smooth
                if faceuv:
                    f_uv = f.uv

                file.write('f')
                if faceuv:
                    if f_smooth:  # Smoothed, use vertex normals
                        for vi, v in enumerate(f_v):
                            file.write( ' %d/%d/%d' % (\
                             v.index+totverts,\
                             totuvco + uv_face_mapping[f_index][vi],\
                             globalNormals[ veckey3d(v.no) ])) # vert, uv, normal

                    else:  # No smoothing, face normals
                        no = globalNormals[veckey3d(f.no)]
                        for vi, v in enumerate(f_v):
                            file.write( ' %d/%d/%d' % (\
                             v.index+totverts,\
                             totuvco + uv_face_mapping[f_index][vi],\
                             no)) # vert, uv, normal

                    face_vert_index += len(f_v)

                else:  # No UV's
                    if f_smooth:  # Smoothed, use vertex normals
                        for v in f_v:
                            file.write( ' %d//%d' % (\
                             v.index+totverts,\
                             globalNormals[ veckey3d(v.no) ]))
                    else:  # No smoothing, face normals
                        no = globalNormals[veckey3d(f.no)]
                        for v in f_v:
                            file.write( ' %d//%d' % (\
                             v.index+totverts,\
                             no))

                file.write('\n')

            # Write edges.
            LOOSE = Mesh.EdgeFlags.LOOSE
            for ed in edges:
                if ed.flag & LOOSE:
                    file.write(
                        'f %d %d\n' %
                        (ed.v1.index + totverts, ed.v2.index + totverts))

            # Make the indicies global rather then per mesh
            totverts += len(me.verts)
            if faceuv:
                totuvco += uv_unique_count
            me.verts = None
    file.close()

    # Now we have all our materials, save them

    print "MESH Export time: %.2f" % (sys.time() - time1)