示例#1
0
def exportProxyObj(human, name, options):
    obj = human.meshData
    cfg = export_config.exportConfig(human, True)
    cfg.separatefolder = True

    stuffs = object_collection.setupObjects(os.path.splitext(name)[0],
                                            human,
                                            helpers=options["helpers"],
                                            hidden=options["hidden"],
                                            eyebrows=options["eyebrows"],
                                            lashes=options["lashes"],
                                            subdivide=options["subdivide"])

    (scale, unit) = options["scale"]
    #name = export_config.goodName(name)
    outfile = export_config.getOutFileFolder(name, cfg)
    (path, ext) = os.path.splitext(outfile)

    filename = "%s_clothed.obj" % path
    fp = open(filename, 'w')
    fp.write("# MakeHuman exported OBJ with clothes\n" +
             "# www.makehuman.org\n\n" +
             "mtllib %s_clothed.obj.mtl\n" % os.path.basename(path))
    for stuff in stuffs:
        writeGeometry(obj, fp, stuff, scale)
    fp.close()

    filename = "%s_clothed.obj.mtl" % path
    fp = open(filename, 'w')
    fp.write('# MakeHuman exported MTL with clothes\n' +
             '# www.makehuman.org\n\n')
    for stuff in stuffs:
        writeMaterial(fp, stuff, human, cfg)
    fp.close()
    return
示例#2
0
def exportFbx(human, filepath, options):
    posemode.exitPoseMode()
    posemode.enterPoseMode()

    the.Human = human
    the.Config = export_config.exportConfig(human, True, [])
    the.Config.separatefolder = True
    outfile = export_config.getOutFileFolder(filepath, the.Config)
    (outpath, ext) = os.path.splitext(outfile)

    log.message("Write FBX file %s" % outfile)

    rawTargets = []
    if options["expressions"]:
        shapeList = read_expression.readExpressionUnits(human, 0, 1)
        rawTargets += shapeList

    if options["customshapes"]:
        the.Config.customshapes = True
        mhx_custom.listCustomFiles(the.Config)

        log.message("Custom shapes:")
        for path, name in the.Config.customShapeFiles:
            log.message("    %s", path)
            shape = mhx_custom.readCustomTarget(path)
            target = (name, shape)
            rawTargets.append(target)

    rigfile = "data/rigs/%s.rig" % options["fbxrig"]
    stuffs = object_collection.setupObjects(
        os.path.splitext(outfile)[0],
        human,
        rigfile,
        rawTargets=rawTargets,
        helpers=options["helpers"],
        hidden=options["hidden"],
        eyebrows=options["eyebrows"],
        lashes=options["lashes"],
    )

    (scale, unit) = options["scale"]

    bpy.initialize()
    name = os.path.splitext(os.path.basename(filepath))[0]
    boneInfo = stuffs[0].boneInfo
    rig = bpy.addRig(name, boneInfo)
    for stuff in stuffs:
        ob = bpy.addMesh(stuff.name, stuff, True)
        ob.parent = rig

    # name = os.path.splitext(os.path.basename(filepath))[0]
    # bpy.addMesh(name, human.meshData, False)

    filename = "%s.fbx" % outpath
    io_mh_fbx.fbx_export.exportFbxFile(bpy.context, filename)
    posemode.exitPoseMode()
    return
示例#3
0
def exportFbx(human, filepath, options):
    posemode.exitPoseMode()        
    posemode.enterPoseMode()
    
    the.Human = human        
    the.Config = export_config.exportConfig(human, True, [])
    the.Config.separatefolder = True
    outfile = export_config.getOutFileFolder(filepath, the.Config)        
    (outpath, ext) = os.path.splitext(outfile)

    log.message("Write FBX file %s" % outfile)

    rawTargets = []
    if options["expressions"]:
        shapeList = read_expression.readExpressionUnits(human, 0, 1)
        rawTargets += shapeList

    if options["customshapes"]:
        the.Config.customshapes = True
        mhx_custom.listCustomFiles(the.Config)                            

        log.message("Custom shapes:")    
        for path,name in the.Config.customShapeFiles:
            log.message("    %s", path)
            shape = mhx_custom.readCustomTarget(path)
            target = (name,shape)
            rawTargets.append(target)

    rigfile = "data/rigs/%s.rig" % options["fbxrig"]
    stuffs = object_collection.setupObjects(
        os.path.splitext(outfile)[0], 
        human, 
        rigfile, 
        rawTargets=rawTargets,
        helpers=options["helpers"], 
        hidden=options["hidden"], 
        eyebrows=options["eyebrows"], 
        lashes=options["lashes"])

    (scale, unit) = options["scale"]   

    bpy.initialize()
    name = os.path.splitext(os.path.basename(filepath))[0]
    boneInfo = stuffs[0].boneInfo
    rig = bpy.addRig(name, boneInfo)
    for stuff in stuffs:
        ob = bpy.addMesh(stuff.name, stuff, True)
        ob.parent = rig
        
    #name = os.path.splitext(os.path.basename(filepath))[0]
    #bpy.addMesh(name, human.meshData, False)
    
    filename = "%s.fbx" % outpath
    io_mh_fbx.fbx_export.exportFbxFile(bpy.context, filename)
    posemode.exitPoseMode()        
    return
示例#4
0
def exportObj_TL(obj, filename):
    """
    This function exports a mesh object in Wavefront obj format. 
    It is assumed that obj will have at least vertices and faces,
    (exception handling for vertices/faces must be done outside this method).

    Parameters
    ----------

    obj:
      *Object3D*.  The object to export.
    filename:
      *string*.  The filename of the file to export the object to.
    """

    # Load all stuff to be rendered - mesh, clothes, polygon hair

    stuffs = object_collection.setupObjects("Mitsuba",
                                            gui3d.app.selectedHuman,
                                            helpers=False,
                                            hidden=False,
                                            eyebrows=False,
                                            lashes=False)

    # Write obj file
    # not is need mtl file. The material is created into Mitsuba .xml file
    # file_mtl = str(filename).replace('.obj','.mtl')

    f = open(filename, 'w')
    f.write('# MakeHuman exported OBJ for Mitsuba\n')
    f.write('# www.makehuman.org\n')
    #

    for stuff in stuffs:
        for v in stuff.verts:
            f.write("v %.4f %.4f %.4f\n" % tuple(v))

    for stuff in stuffs:
        for uv in stuff.uvValues:
            f.write("vt %.4f %.4f\n" % tuple(uv))

    nVerts = 1
    nUvVerts = 1
    for stuff in stuffs:
        for fc in stuff.faces:
            f.write('f ')
            for vs in fc:
                f.write("%d/%d " % (vs[0] + nVerts, vs[1] + nUvVerts))
            f.write('\n')
        nVerts += len(stuff.verts)
        nUvVerts += len(stuff.uvValues)

    f.close()
示例#5
0
def exportObj_TL(obj, filename):
    """
    This function exports a mesh object in Wavefront obj format. 
    It is assumed that obj will have at least vertices and faces,
    (exception handling for vertices/faces must be done outside this method).

    Parameters
    ----------

    obj:
      *Object3D*.  The object to export.
    filename:
      *string*.  The filename of the file to export the object to.
    """

    # Load all stuff to be rendered - mesh, clothes, polygon hair

    stuffs = object_collection.setupObjects("Mitsuba", gui3d.app.selectedHuman, helpers=False, hidden=False, eyebrows=False, lashes=False)

    # Write obj file
    # not is need mtl file. The material is created into Mitsuba .xml file
    # file_mtl = str(filename).replace('.obj','.mtl')

    f = open(filename, 'w')
    f.write('# MakeHuman exported OBJ for Mitsuba\n')
    f.write('# www.makehuman.org\n')
    # 

    for stuff in stuffs:
        for v in stuff.verts:
            f.write("v %.4f %.4f %.4f\n" % tuple(v))

    for stuff in stuffs:
        for uv in stuff.uvValues:
            f.write("vt %.4f %.4f\n" % tuple(uv))

    nVerts = 1
    nUvVerts = 1
    for stuff in stuffs:
        for fc in stuff.faces:
            f.write('f ')
            for vs in fc:
                f.write("%d/%d " % (vs[0]+nVerts, vs[1]+nUvVerts))
            f.write('\n')
        nVerts += len(stuff.verts)
        nUvVerts += len(stuff.uvValues)
    
    f.close()
示例#6
0
def exportProxyObj(human, name, options):
    obj = human.meshData
    cfg = export_config.exportConfig(human, True)
    cfg.separatefolder = True

    stuffs = object_collection.setupObjects(os.path.splitext(name)[0], human,
        helpers=options["helpers"], 
        hidden=options["hidden"], 
        eyebrows=options["eyebrows"], 
        lashes=options["lashes"],
        subdivide=options["subdivide"])
    
    (scale, unit) = options["scale"]   
    #name = export_config.goodName(name)
    outfile = export_config.getOutFileFolder(name, cfg)   
    (path, ext) = os.path.splitext(outfile)

    filename = "%s_clothed.obj" % path
    fp = open(filename, 'w')
    fp.write(
"# MakeHuman exported OBJ with clothes\n" +
"# www.makehuman.org\n\n" +
"mtllib %s_clothed.obj.mtl\n" % os.path.basename(path))
    for stuff in stuffs:
        writeGeometry(obj, fp, stuff, scale)
    fp.close()
    
    filename = "%s_clothed.obj.mtl" % path
    fp = open(filename, 'w')
    fp.write(
'# MakeHuman exported MTL with clothes\n' +
'# www.makehuman.org\n\n')
    for stuff in stuffs:
        writeMaterial(fp, stuff, human, cfg)
    fp.close()
    return
示例#7
0
def exportDae(human, name, fp):
    cfg = export_config.exportConfig(human, True)
    obj = human.meshData
    rigfile = "data/rigs/%s.rig" % the.Options["daerig"]

    stuffs = object_collection.setupObjects(
        name, 
        human, 
        rigfile=rigfile, 
        helpers=the.Options["helpers"], 
        hidden=the.Options["hidden"], 
        eyebrows=the.Options["eyebrows"], 
        lashes=the.Options["lashes"])
    mainStuff = stuffs[0]        

    date = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())
    if the.Rotate90X:
        upaxis = 'Z_UP'
    else:
        upaxis = 'Y_UP'
    (scale, unit) = the.Options["scale"]        
        
    fp.write('<?xml version="1.0" encoding="utf-8"?>\n' +
'<COLLADA version="1.4.0" xmlns="http://www.collada.org/2005/11/COLLADASchema">\n' +
'  <asset>\n' +
'    <contributor>\n' +
'      <author>www.makehuman.org</author>\n' +
'    </contributor>\n' +
'    <created>%s</created>\n' % date +
'    <modified>%s</modified>\n' % date +
'    <unit meter="%.4f" name="%s"/>\n' % (0.1/scale, unit) +
'    <up_axis>%s</up_axis>\n' % upaxis+
'  </asset>\n' +
'  <library_images>\n')

    for stuff in stuffs:
        writeImages(obj, fp, stuff, human)

    fp.write(
'  </library_images>\n' +
'  <library_effects>\n')

    for stuff in stuffs:
        writeEffects(obj, fp, stuff)

    fp.write(
'  </library_effects>\n' +
'  <library_materials>\n')

    for stuff in stuffs:
        writeMaterials(obj, fp, stuff)

    fp.write(
'  </library_materials>\n'+
'  <library_controllers>\n')

    for stuff in stuffs:
        writeController(obj, fp, stuff)

    fp.write(
'  </library_controllers>\n'+
'  <library_geometries>\n')

    for stuff in stuffs:
        writeGeometry(obj, fp, stuff)

    fp.write(
'  </library_geometries>\n\n' +
'  <library_visual_scenes>\n' +
'    <visual_scene id="Scene" name="Scene">\n' +
'      <node id="Scene_root">\n')
    for root in mainStuff.boneInfo.hier:
        writeBone(fp, root, [0,0,0], 'layer="L1"', '  ', mainStuff)
    for stuff in stuffs:
        writeNode(obj, fp, "        ", stuff)

    fp.write(
'      </node>\n' +    
'    </visual_scene>\n' +
'  </library_visual_scenes>\n' +
'  <scene>\n' +
'    <instance_visual_scene url="#Scene"/>\n' +
'  </scene>\n' +
'</COLLADA>\n')
    return
示例#8
0
def povrayExportMesh2_TL(obj, camera, resolution, path, settings, progressCallback = None):
    """
    This function exports data in the form of a mesh2 humanoid object. The POV-Ray 
    file generated is fairly inflexible, but is highly efficient. 

    Parameters
    ----------

    obj:
      *3D object*. The object to export. This should be the humanoid object with
      uv-mapping data and Face Groups defined.

    camera:
      *Camera object*. The camera to render from. 

    path:
      *string*. The file system path to the output files that need to be generated.

    settings:
      *dictionary*. Settings passed from the GUI.
    """

    progbase = 0
    def progress (base, prog, desc):
        if progressCallback == None:
            gui3d.app.progress(base + prog, desc)
        else:
            progressCallback(base + prog, desc)

    # Certain blocks of SDL are mostly static and can be copied directly from reference
    # files into the output files.
    progress (progbase,0,"Parsing data")
    progbase = progbase + 0.05
    headerFile = 'data/povray/headercontent_mesh2only.inc'
    staticFile = 'data/povray/staticcontent_mesh2only_fsss.inc' if settings['SSS'] == True else 'data/povray/staticcontent_mesh2only_tl.inc'
    sceneFile = 'data/povray/makehuman_mesh2only_tl.pov'
    pigmentMap = gui3d.app.selectedHuman.mesh.texture

    # Define some additional file locations
    outputSceneFile = path.replace('.inc', '.pov')
    baseName = os.path.basename(path)
    nameOnly = string.replace(baseName, '.inc', '')
    underScores = ''.ljust(len(baseName), '-')
    outputDirectory = os.path.dirname(path)

    # Make sure the directory exists
    if not os.path.isdir(outputDirectory):
        try:
            os.makedirs(outputDirectory)
        except:
            log.error('Error creating export directory.')
            return 0

    # If fake SSS is enabled, render lightmaps there. # TODO: if they aren't already rendered.
    if settings['SSS'] == True:
        # calculate resolution of each cannel, according to settings
        resred = float(settings['SSSA'])
        resgreen = int(2.0**(10-resred/2))
        resred = int(2.0**(10-resred))
        # blue channel
        lmap = projection.mapLighting(progressCallback = lambda p: progress(progbase,p*(0.55-progbase),"Rendering lightmaps"))
        log.debug('SSS: Hi-Res lightmap resolution: %s', lmap.width)
        lmap.save(os.path.join(outputDirectory, 'lighthi.png'))
        # green channel
        lmap.resize(resgreen,resgreen)
        log.debug('SSS: Mid-Res lightmap resolution: %s', lmap.width)
        lmap.save(os.path.join(outputDirectory, 'lightmid.png'))
        # red channel
        lmap.resize(resred,resred)
        log.debug('SSS: Low-Res lightmap resolution: %s', lmap.width)
        lmap.save(os.path.join(outputDirectory, 'lightlo.png'))
        progbase = 0.55

    # Open the output file in Write mode
    progress(progbase,0,"Writing code")
    progbase = progbase + 0.5
    try:
        outputFileDescriptor = open(path, 'w')
    except:
        log.error('Error opening file to write data.')
        return 0

    # Write the file name into the top of the comment block that starts the file.
    outputFileDescriptor.write('// %s\n' % baseName)
    outputFileDescriptor.write('// %s\n' % underScores)

    # Copy the header file SDL straight across to the output file
    try:
        headerFileDescriptor = open(headerFile, 'r')
    except:
        log.error('Error opening file to read standard headers.')
        return 0
    headerLines = headerFileDescriptor.read()
    outputFileDescriptor.write(headerLines)
    outputFileDescriptor.write('''

''')
    headerFileDescriptor.close()

    # Declare POV Ray variables containing the current makehuman camera.
    povrayCameraData(camera, resolution, outputFileDescriptor, settings)
    
    # Declare POV Ray variables containing the current object position and rotation.
    outputFileDescriptor.write('#declare MakeHuman_TranslateX      = %s;\n' % -obj.x)
    outputFileDescriptor.write('#declare MakeHuman_TranslateY      = %s;\n' % obj.y)
    outputFileDescriptor.write('#declare MakeHuman_TranslateZ      = %s;\n\n' % obj.z)
    outputFileDescriptor.write('#declare MakeHuman_RotateX         = %s;\n' % obj.rx)
    outputFileDescriptor.write('#declare MakeHuman_RotateY         = %s;\n' % -obj.ry)
    outputFileDescriptor.write('#declare MakeHuman_RotateZ         = %s;\n\n' % obj.rz)

    # Calculate some useful values and add them to the output as POV-Ray variable
    # declarations so they can be readily accessed from a POV-Ray scene file.

    povraySizeData(obj, outputFileDescriptor)

    stuffs = object_collection.setupObjects("MakeHuman", gui3d.app.selectedHuman, helpers=False, hidden=False,
                                            eyebrows=False, lashes=False, subdivide = settings['subdivide'],
                                            progressCallback = lambda p: progress(progbase,p*(0.75-progbase),"Preparing Objects"))
    progbase = 0.75

    # Mesh2 Object - Write the initial part of the mesh2 object declaration
    progress(progbase,0,"Writing objects")
    for stuff in stuffs:

        outputFileDescriptor.write('// Humanoid mesh2 definition\n')
        outputFileDescriptor.write('#declare %s_Mesh2Object = mesh2 {\n' % stuff.name)

        # Vertices - Write a POV-Ray array to the output stream
        outputFileDescriptor.write('  vertex_vectors {\n  ')
        outputFileDescriptor.write('    %s\n  ' % len(stuff.meshInfo.verts))

        for v in stuff.meshInfo.verts:
            outputFileDescriptor.write('<%s,%s,%s>' % (-v[0],v[1],v[2]))
        outputFileDescriptor.write('''
  }

''')

        # Normals - Write a POV-Ray array to the output stream
        outputFileDescriptor.write('  normal_vectors {\n  ')
        outputFileDescriptor.write('    %s\n  ' % len(stuff.meshInfo.verts))
        for vno in stuff.meshInfo.vnormals:
            outputFileDescriptor.write('<%s,%s,%s>' % (-vno[0],vno[1],vno[2]))

        outputFileDescriptor.write('''
  }

''')
    
        # UV Vectors - Write a POV-Ray array to the output stream
        outputFileDescriptor.write('  uv_vectors {\n  ')
        outputFileDescriptor.write('    %s\n  ' % len(stuff.meshInfo.uvValues))
        for uv in stuff.meshInfo.uvValues:
            outputFileDescriptor.write('<%s,%s>' % tuple(uv))        

        outputFileDescriptor.write('''
  }

''')

        # Faces - Write a POV-Ray array of arrays to the output stream
        nTriangles = 0
        for f in stuff.meshInfo.faces:
            nTriangles += len(f)-2

        outputFileDescriptor.write('  face_indices {\n  ')
        outputFileDescriptor.write('    %s\n  ' % nTriangles)

        for f in stuff.meshInfo.faces:
            verts = []
            for v,vt in f:
                verts.append(v)
            outputFileDescriptor.write('<%s,%s,%s>' % (verts[0], verts[1], verts[2]))
            if len(verts) == 4:
                outputFileDescriptor.write('<%s,%s,%s>' % (verts[2], verts[3], verts[0]))

        outputFileDescriptor.write('''
  }

''')


        # UV Indices for each face - Write a POV-Ray array to the output stream
        outputFileDescriptor.write('  uv_indices {\n  ')
        outputFileDescriptor.write('    %s\n  ' % nTriangles)

        for f in stuff.meshInfo.faces:
            vts = []
            for v,vt in f:
                vts.append(vt)        
            outputFileDescriptor.write('<%s,%s,%s>' % (vts[0], vts[1], vts[2]))
            if len(vts) == 4:
                outputFileDescriptor.write('<%s,%s,%s>' % (vts[2], vts[3], vts[0]))

        outputFileDescriptor.write('''
  }
''')

        # Mesh2 Object - Write the end squiggly bracket for the mesh2 object declaration
        outputFileDescriptor.write('''
      uv_mapping
''')
        outputFileDescriptor.write('''}

''')
    progbase = 0.85
                                            
    # Copy texture definitions to the output file.
    progress(progbase,0,"Writing Materials")
    try:
        staticContentFileDescriptor = open(staticFile, 'r')
    except:
        log.error('Error opening file to read static content.')
        return 0
    staticContentLines = staticContentFileDescriptor.read()
    staticContentLines = string.replace(staticContentLines, '%%skinoil%%', str(settings['skinoil']))    
    staticContentLines = string.replace(staticContentLines, '%%rough%%', str(settings['rough']))    
    staticContentLines = string.replace(staticContentLines, '%%wrinkles%%', str(settings['wrinkles']))    
    outputFileDescriptor.write(staticContentLines)
    outputFileDescriptor.write('\n')
    staticContentFileDescriptor.close()
    
    # Write items' materials 
    writeItemsMaterials(outputFileDescriptor, stuffs, settings, outputDirectory)
             
    # The POV-Ray include file is complete
    outputFileDescriptor.close()
    log.message("POV-Ray '#include' file generated.")
    progbase = 0.95

    # Copy a sample scene file across to the output directory
    progress(progbase,0,"Writing Scene file")
    try:
        sceneFileDescriptor = open(sceneFile, 'r')
    except:
        log.error('Error opening file to read standard scene file.')
        return 0
    try:
        outputSceneFileDescriptor = open(outputSceneFile, 'w')
    except:
        log.error('Error opening file to write standard scene file.')
        return 0
    sceneLines = sceneFileDescriptor.read()
    sceneLines = string.replace(sceneLines, 'xxFileNamexx', nameOnly)
    sceneLines = string.replace(sceneLines, 'xxUnderScoresxx', underScores)
    sceneLines = string.replace(sceneLines, 'xxLowercaseFileNamexx', nameOnly.lower())
    outputSceneFileDescriptor.write(sceneLines)
    
    for stuff in stuffs:
        outputSceneFileDescriptor.write(
            "object { \n" +
            "   %s_Mesh2Object \n" % stuff.name +
            "   rotate <0, 0, MakeHuman_RotateZ> \n" +
            "   rotate <0, MakeHuman_RotateY, 0> \n" +
            "   rotate <MakeHuman_RotateX, 0, 0> \n" +
            "   translate <MakeHuman_TranslateX, MakeHuman_TranslateY, MakeHuman_TranslateZ> \n" +
            "   material {%s_Material} \n" % stuff.name +
            "}  \n")

    # Job done, clean up
    outputSceneFileDescriptor.close()
    sceneFileDescriptor.close()
    progbase = 1

    # Copy the skin texture file into the output directory
    progress(progbase,0,"Finishing")
    copyFile(pigmentMap, os.path.join(outputDirectory, "texture.png"))

    for stuff in stuffs[1:]:
        if stuff.texture:
            copyFile(stuff.texture, outputDirectory)
        """
        if proxy.normal:
            copyFile(proxy.normal, outputDirectory)
        if proxy.bump:
            copyFile(proxy.bump, outputDirectory)
        if proxy.displacement:
            copyFile(proxy.displacement, outputDirectory)
        if proxy.transparency:
            copyFile(proxy.transparency, outputDirectory)
        """

    log.message('Sample POV-Ray scene file generated')
    progress(0,0,"Finished. Pov-Ray project exported successfully at %s" % outputDirectory)
示例#9
0
def exportDae(human, name, fp):
    cfg = export_config.exportConfig(human, True)
    obj = human.meshData
    rigfile = "data/rigs/%s.rig" % the.Options["daerig"]

    stuffs = object_collection.setupObjects(name,
                                            human,
                                            rigfile=rigfile,
                                            helpers=the.Options["helpers"],
                                            hidden=the.Options["hidden"],
                                            eyebrows=the.Options["eyebrows"],
                                            lashes=the.Options["lashes"])
    mainStuff = stuffs[0]

    date = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())
    if the.Rotate90X:
        upaxis = 'Z_UP'
    else:
        upaxis = 'Y_UP'
    (scale, unit) = the.Options["scale"]

    fp.write(
        '<?xml version="1.0" encoding="utf-8"?>\n' +
        '<COLLADA version="1.4.0" xmlns="http://www.collada.org/2005/11/COLLADASchema">\n'
        + '  <asset>\n' + '    <contributor>\n' +
        '      <author>www.makehuman.org</author>\n' + '    </contributor>\n' +
        '    <created>%s</created>\n' % date +
        '    <modified>%s</modified>\n' % date +
        '    <unit meter="%.4f" name="%s"/>\n' % (0.1 / scale, unit) +
        '    <up_axis>%s</up_axis>\n' % upaxis + '  </asset>\n' +
        '  <library_images>\n')

    for stuff in stuffs:
        writeImages(obj, fp, stuff, human)

    fp.write('  </library_images>\n' + '  <library_effects>\n')

    for stuff in stuffs:
        writeEffects(obj, fp, stuff)

    fp.write('  </library_effects>\n' + '  <library_materials>\n')

    for stuff in stuffs:
        writeMaterials(obj, fp, stuff)

    fp.write('  </library_materials>\n' + '  <library_controllers>\n')

    for stuff in stuffs:
        writeController(obj, fp, stuff)

    fp.write('  </library_controllers>\n' + '  <library_geometries>\n')

    for stuff in stuffs:
        writeGeometry(obj, fp, stuff)

    fp.write('  </library_geometries>\n\n' + '  <library_visual_scenes>\n' +
             '    <visual_scene id="Scene" name="Scene">\n' +
             '      <node id="Scene_root">\n')
    for root in mainStuff.boneInfo.hier:
        writeBone(fp, root, [0, 0, 0], 'layer="L1"', '  ', mainStuff)
    for stuff in stuffs:
        writeNode(obj, fp, "        ", stuff)

    fp.write('      </node>\n' + '    </visual_scene>\n' +
             '  </library_visual_scenes>\n' + '  <scene>\n' +
             '    <instance_visual_scene url="#Scene"/>\n' + '  </scene>\n' +
             '</COLLADA>\n')
    return