def setupProxySkinning(self):
        # Remove all meshes but the human and skeleton mesh from the animatedMesh object
        for mName in self.human.animated.getMeshes()[2:]:
            self.human.animated.removeMesh(mName)
            # TODO it's more optimized not to remove all proxy object meshes every time

        _, bodyWeights = self.human.animated.getMesh("base.obj")

        # Proxy mesh (always animate)
        if self.human.proxy and self.human.isProxied():
            weights = skeleton.getProxyWeights(self.human.proxy, bodyWeights, self.human.getProxyMesh())
            self.human.animated.addMesh(self.human.getProxyMesh(), weights)

        # Generate a vertex-to-bone mapping derived from that of the human for all proxy objects
        if self.skinProxiesTggl.selected:
            # Clothes
            for (name,obj) in self.human.clothesObjs.items():
                proxy = self.human.clothesProxies[name]
                weights = skeleton.getProxyWeights(proxy, bodyWeights, obj.mesh)
                self.human.animated.addMesh(obj.mesh, weights)
                obj.show()

            # Hair
            if self.human.hairObj and self.human.hairProxy:
                weights = skeleton.getProxyWeights(self.human.hairProxy, bodyWeights, self.human.hairObj.mesh)
                self.human.animated.addMesh(self.human.hairObj.mesh, weights)
                self.human.hairObj.show()
        else:
            # Hide not animated proxies (clothes and hair)
            for (name,obj) in self.human.clothesObjs.items():
                obj.hide()
            if self.human.hairObj:
                self.human.hairObj.hide()
Ejemplo n.º 2
0
    def setupProxySkinning(self):
        # Remove all meshes but the human and skeleton mesh from the animatedMesh object
        for mName in self.human.animated.getMeshes()[2:]:
            self.human.animated.removeMesh(mName)
            # TODO it's more optimized not to remove all proxy object meshes every time

        _, bodyWeights = self.human.animated.getMesh("base.obj")

        # Proxy mesh (always animate)
        if self.human.proxy and self.human.isProxied():
            weights = skeleton.getProxyWeights(self.human.proxy, bodyWeights,
                                               self.human.getProxyMesh())
            self.human.animated.addMesh(self.human.getProxyMesh(), weights)

        # Generate a vertex-to-bone mapping derived from that of the human for all proxy objects
        if self.skinProxiesTggl.selected:
            # Clothes
            for (name, obj) in self.human.clothesObjs.items():
                proxy = self.human.clothesProxies[name]
                weights = skeleton.getProxyWeights(proxy, bodyWeights,
                                                   obj.mesh)
                self.human.animated.addMesh(obj.mesh, weights)
                obj.show()

            # Hair
            if self.human.hairObj and self.human.hairProxy:
                weights = skeleton.getProxyWeights(self.human.hairProxy,
                                                   bodyWeights,
                                                   self.human.hairObj.mesh)
                self.human.animated.addMesh(self.human.hairObj.mesh, weights)
                self.human.hairObj.show()
        else:
            # Hide not animated proxies (clothes and hair)
            for (name, obj) in self.human.clothesObjs.items():
                obj.hide()
            if self.human.hairObj:
                self.human.hairObj.hide()
Ejemplo n.º 3
0
    def setupProxySkinning(self):
        # Remove all meshes but the human and skeleton mesh from the animatedMesh object
        for mName in self.human.animated.getMeshes()[2:]:
            self.human.animated.removeMesh(mName)
            # TODO it's more optimized not to remove all proxy object meshes every time

        _, bodyWeights = self.human.animated.getMesh("base.obj")

        # Proxy mesh (always animate)
        if self.human.proxy and self.human.isProxied():
            weights = skeleton.getProxyWeights(self.human.proxy, bodyWeights,
                                               self.human.getProxyMesh())
            self.human.animated.addMesh(self.human.getProxyMesh(), weights)

        # Generate a vertex-to-bone mapping derived from that of the human for all proxy objects
        if self.skinProxiesTggl.selected:
            for proxy, obj in self.human.getProxiesAndObjects():
                weights = skeleton.getProxyWeights(proxy, bodyWeights,
                                                   obj.mesh)
                self.human.animated.addMesh(obj.mesh, weights)
                obj.show()
        else:
            for obj in self.human.getProxyObjects():
                obj.hide()
Ejemplo n.º 4
0
def exportMd5(filepath, config):
    """
    This function exports MakeHuman mesh and skeleton data to id Software's MD5 format.

    Parameters
    ----------

    human:
      *Human*.  The object whose information is to be used for the export.
    filepath:
      *string*.  The filepath of the file to export the object to.
    config:
      *Config*.  Export configuration.
    """

    progress = Progress.begin(logging=True, timing=True)

    human = config.human
    obj = human.meshData
    config.zUp = True
    config.feetOnGround = True    # TODO this only works when exporting MHX mesh (a design error in exportutils)
    config.scale = 1
    config.setupTexFolder(filepath)
    filename = os.path.basename(filepath)
    name = config.goodName(os.path.splitext(filename)[0])

    humanBBox = human.meshData.calcBBox()

    progress(0, 0.2, "Collecting Objects")
    rmeshes = exportutils.collect.setupMeshes(
        name,
        human,
        config=config,
        subdivide=config.subdivide)

    if human.getSkeleton():
        numJoints = human.getSkeleton().getBoneCount() +1 # Amount of joints + the hardcoded origin below
    else:
        numJoints = 1

    f = codecs.open(filepath, 'w', encoding="utf-8")
    f.write('MD5Version 10\n')
    f.write('commandline ""\n\n')
    f.write('numJoints %d\n' % numJoints)
    f.write('numMeshes %d\n\n' % (len(rmeshes)))

    f.write('joints {\n')
    # Hardcoded root joint
    f.write('\t"%s" %d ( %f %f %f ) ( %f %f %f )\n' % ('origin', -1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0))
    progress(0.2, 0.3, "Writing Bones")
    if human.getSkeleton():
        bones = human.getSkeleton().getBones()
        boneprog = Progress(len(bones))
        for bone in bones:
            writeBone(f, bone, human, config)
            boneprog.step()
    f.write('}\n\n')

    progress(0.3, 0.8, "Writing Objects")
    loopprog = Progress(len(rmeshes))
    for rmeshIdx, rmesh in enumerate(rmeshes):
        # rmesh.type: None is human, "Proxymeshes" is human proxy, "Clothes" for clothing and "Hair" for hair
        objprog = Progress()
        objprog(0.0, 0.1, "Writing %s mesh." % rmesh.name)

        obj = rmesh.object

        obj.calcFaceNormals()
        obj.calcVertexNormals()
        obj.updateIndexBuffer()

        numVerts = len(obj.r_coord)
        if obj.vertsPerPrimitive == 4:
            # Quads
            numFaces = len(obj.r_faces) * 2
        else:
            # Tris
            numFaces = len(obj.r_faces)

        f.write('mesh {\n')
        mat = rmesh.material
        if mat.diffuseTexture:
            tex = copyTexture(mat.diffuseTexture, human, config)
            f.write('\tshader "%s"\n' % tex)

        f.write('\n\tnumverts %d\n' % numVerts)

        # Collect vertex weights
        if human.getSkeleton():
            objprog(0.1, 0.2, "Writing skeleton")
            bodyWeights = human.getVertexWeights()

            if rmesh.type:
                # Determine vertex weights for proxy
                weights = skeleton.getProxyWeights(rmesh.proxy, bodyWeights, obj)
            else:
                # Use vertex weights for human body
                weights = bodyWeights
                # Account for vertices that are filtered out
                if rmesh.vertexMapping != None:
                    filteredVIdxMap = rmesh.vertexMapping
                    weights2 = {}
                    for (boneName, (verts,ws)) in weights.items():
                        verts2 = []
                        ws2 = []
                        for i, vIdx in enumerate(verts):
                            if vIdx in filteredVIdxMap:
                                verts2.append(filteredVIdxMap[vIdx])
                                ws2.append(ws[i])
                        weights2[boneName] = (verts2, ws2)
                    weights = weights2

            # Remap vertex weights to the unwelded vertices of the object (obj.coord to obj.r_coord)
            originalToUnweldedMap = obj.inverse_vmap

            # Build a weights list indexed per vertex
            jointIndexes = {}
            jointIndexes['origin'] = 0
            joints = [None] + human.getSkeleton().getBones() # origin joint is None
            for idx,bone in enumerate(joints):
                if bone:
                    jointIndexes[bone.name] = idx
            vertWeights = {}    # = dict( vertIdx: [ (jointIdx1, weight1), ...])
            for (jointName, (verts,ws)) in weights.items():
                jointIdx = jointIndexes[jointName]
                for idx,v in enumerate(verts):
                    try:
                        for r_vIdx in originalToUnweldedMap[v]:
                            if r_vIdx not in vertWeights:
                                vertWeights[r_vIdx] = []
                            vertWeights[r_vIdx].append((jointIdx, ws[idx]))
                    except:
                        # unused coord
                        pass
            for vert in xrange(numVerts):
                if vert not in vertWeights:
                    # Weight vertex completely to origin joint
                    vertWeights[vert] = [(0, 1.0)]
        else:
            vertWeights = None

        objprog(0.3, 0.7, "Writing vertices for %s." % rmesh.name)
        # Write vertices
        wCount = 0
        for vert in xrange(numVerts):
            if obj.has_uv:
                u, v = obj.r_texco[vert]
            else:
                u, v = 0, 0
            if vertWeights == None:
                numWeights = 1
            else:
                numWeights = len(vertWeights[vert])
            # vert [vertIndex] ( [texU] [texV] ) [weightIndex] [weightElem]
            f.write('\tvert %d ( %f %f ) %d %d\n' % (vert, u, 1.0-v, wCount, numWeights))
            wCount = wCount + numWeights

        objprog(0.7, 0.8, "Writing faces for %s." % rmesh.name)
        # Write faces
        f.write('\n\tnumtris %d\n' % numFaces)
        fn = 0
        for fv in obj.r_faces:
            # tri [triIndex] [vertIndex1] [vertIndex2] [vertIndex3]
            f.write('\ttri %d %d %d %d\n' % (fn, fv[2], fv[1], fv[0]))
            fn += 1
            if fv[0] != fv[3]:
                f.write('\ttri %d %d %d %d\n' % (fn, fv[0], fv[3], fv[2]))
                fn += 1

        objprog(0.8, 0.99, "Writing bone weights for %s." % rmesh.name)
        # Write bone weighting
        bwprog = Progress(len(obj.r_coord)).HighFrequency(200)
        if human.getSkeleton():
            f.write('\n\tnumweights %d\n' % wCount)
            wCount = 0
            for idx,co in enumerate(obj.r_coord):
                for (jointIdx, jointWght) in vertWeights[idx]:
                    # Get vertex position in bone space
                    if joints[jointIdx]:
                        invbonematrix = joints[jointIdx].matRestGlobal.copy()
                        invbonematrix[:3,3] = [0,0,0]
                        invbonematrix = la.inv(invbonematrix)
                        relPos = np.ones(4, dtype=np.float32)
                        relPos[:3] = co[:3]
                        relPos[:3] -= joints[jointIdx].getRestHeadPos()
                        relPos[:3] *= scale
                        #relPos = np.dot(relPos, invbonematrix)
                    else:
                        relPos = co[:3] * scale

                    if config.zUp:
                        relPos[:3] = relPos[[0,2,1]] * [1,-1,1]

                    # weight [weightIndex] [jointIndex] [weightValue] ( [xPos] [yPos] [zPos] )
                    f.write('\tweight %d %d %f ( %f %f %f )\n' % (wCount, jointIdx, jointWght, relPos[0], relPos[1], relPos[2]))
                    wCount = wCount +1
                bwprog.step()
        else:
            # No skeleton selected: Attach all vertices to the root with weight 1.0
            f.write('\n\tnumweights %d\n' % (numVerts))
            for idx,co in enumerate(obj.r_coord):
                # weight [weightIndex] [jointIndex] [weightValue] ( [xPos] [yPos] [zPos] )
                co = co.copy() * scale

                if config.feetOnGround:
                    co[1] += (getFeetOnGroundOffset(human) * scale)

                if config.zUp:
                    co = co[[0,2,1]] * [1,-1,1]

                f.write('\tweight %d %d %f ( %f %f %f )\n' % (idx, 0, 1.0, co[0], co[1], co[2]))
                # Note: MD5 has a z-up coordinate system
                bwprog.step()
        f.write('}\n\n')
        loopprog.step()
    f.close()

    progress(0.8, 0.99, "Writing Animations")
    if human.getSkeleton() and hasattr(human, 'animations'):
        animprog = Progress(len(human.animations))
        for anim in human.animations:
            writeAnimation(filepath, human, humanBBox, config, anim.getAnimationTrack())
            animprog.step()

    progress(1, None, "MD5 export finished. Exported file: %s", filepath)
Ejemplo n.º 5
0
def addGeometry(mhGeos, mesh, skel, rawWeights, mats, mname, cfg):

    mhGeo = OrderedDict()
    mhGeos.append(mhGeo)

    obj = mesh.object
    pxy = obj.proxy
    if pxy:
        if pxy.type == 'Proxymeshes':
            mhGeo["license"] = BaseMeshLicense
        else:
            addProxyLicense(mhGeo, pxy)
    else:
        mhGeo["license"] = BaseMeshLicense

    mhName = mhGeo["name"] = mname
    mhGeo["uuid"] = str(uuid4())
    mhGeo["offset"] = cfg.offset
    mhGeo["scale"] = cfg.scale
    mhGeo["issubdivided"] = obj.isSubdivided()
    try:
        mhGeo["material"] = mats[mesh.name]
    except KeyError:
        pass

    mhMesh = mhGeo["mesh"] = OrderedDict()
    if pxy and pxy.type == 'Proxymeshes':
        addMesh(mhMesh, mesh.clone())
    else:
        addMesh(mhMesh, mesh)
    mhSeed = mhGeo["seed_mesh"] = OrderedDict()
    obj = mesh.object
    addMesh(mhSeed, obj.getSeedMesh())

    if pxy:
        if pxy.type == 'Proxymeshes':
            mhGeo["human"] = True
            mhProxySeed = mhGeo["proxy_seed_mesh"] = OrderedDict()
            addMesh(mhProxySeed, obj.getProxyMesh())
        else:
            mhGeo["human"] = False
            mhProxySeed = None

        if skel:
            if hasattr(mesh, "getVertexWeights"):
                pxySeedWeights = pxy.getVertexWeights(rawWeights, skel)
                weights = mesh.getVertexWeights(pxySeedWeights)
            else:
                pxySeedWeights = skeleton.getProxyWeights(pxy, rawWeights)
                weights = mesh.getWeights(pxySeedWeights)

            addWeights(mhMesh, skel, weights)
            if mhProxySeed:
                addWeights(mhSeed, skel, rawWeights)
                addWeights(mhProxySeed, skel, pxySeedWeights)
            else:
                addWeights(mhSeed, skel, pxySeedWeights)

        mhProxy = mhGeo["proxy"] = OrderedDict()
        addProxyLicense(mhProxy, pxy)
        mhProxy["name"] = pxy.name.capitalize()
        mhProxy["type"] = pxy.type
        mhProxy["uuid"] = pxy.uuid
        mhProxy["basemesh"] = pxy.basemesh
        mhProxy["tags"] = list(pxy.tags)

        mhProxy["fitting"] = np.array([(vnums, pxy.weights[n], pxy.offsets[n])
                                       for n, vnums in enumerate(pxy.ref_vIdxs)
                                       ])
        #mhProxy["ref_wvIdxs"] = pxy.ref_wvIdxs
        mhProxy["delete_verts"] = pxy.deleteVerts
        if hasattr(pxy, "vertexBoneWeights") and pxy.vertexBoneWeights:
            mhProxy["vertex_bone_weights"] = pxy.vertexBoneWeights.data
        else:
            mhProxy["vertex_bone_weights"] = None
    else:
        mhGeo["human"] = True
        if skel:
            addWeights(mhSeed, skel, rawWeights)
            if hasattr(mesh, "getVertexWeights"):
                weights = mesh.getVertexWeights(rawWeights)
            else:
                weights = mesh.getWeights(rawWeights)
            addWeights(mhMesh, skel, weights)
Ejemplo n.º 6
0
def writeMeshFile(human, filepath, rmeshes, config, progressCallback=None):
    progress = Progress(len(rmeshes))

    filename = os.path.basename(filepath)
    name = formatName(config.goodName(os.path.splitext(filename)[0]))

    f = codecs.open(filepath, 'w', encoding="utf-8")
    f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
    f.write('<!-- Exported from MakeHuman (www.makehuman.org) -->\n')
    f.write('<mesh>\n')
    f.write('    <submeshes>\n')

    for rmeshIdx, rmesh in enumerate(rmeshes):
        loopprog = Progress()(0.0, 0.1, "Writing %s mesh." % rmesh.name)
        obj = rmesh.object
        # Make sure vertex normals are calculated
        obj.calcFaceNormals()
        obj.calcVertexNormals()
        # Calculate rendering data so we can use the unwelded vertices
        obj.updateIndexBuffer()
        numVerts = len(obj.r_coord)

        if obj.vertsPerPrimitive == 4:
            # Quads
            numFaces = len(obj.r_faces) * 2
        else:
            # Tris
            numFaces = len(obj.r_faces)

        loopprog(0.1, 0.3, "Writing faces of %s." % rmesh.name)
        f.write(
            '        <submesh material="%s_%s_%s" usesharedvertices="false" use32bitindexes="false" operationtype="triangle_list">\n'
            % (formatName(name), rmeshIdx, formatName(rmesh.name)
               if formatName(rmesh.name) != name else "human"))

        # Faces
        f.write('            <faces count="%s">\n' % numFaces)
        for fv in obj.r_faces:
            f.write('                <face v1="%s" v2="%s" v3="%s" />\n' %
                    (fv[0], fv[1], fv[2]))
            if obj.vertsPerPrimitive == 4:
                f.write('                <face v1="%s" v2="%s" v3="%s" />\n' %
                        (fv[2], fv[3], fv[0]))
        f.write('            </faces>\n')

        loopprog(0.3, 0.7, "Writing vertices of %s." % rmesh.name)
        # Vertices
        f.write('            <geometry vertexcount="%s">\n' % numVerts)
        f.write(
            '                <vertexbuffer positions="true" normals="true">\n')
        #f.write('                <vertexbuffer positions="true">\n')
        for vIdx, co in enumerate(obj.r_coord):
            if config.feetOnGround:
                co = co.copy()
                co[1] += getFeetOnGroundOffset(human)

            # Note: Ogre3d uses a y-up coordinate system (just like MH)
            norm = obj.r_vnorm[vIdx]
            f.write('                    <vertex>\n')
            f.write(
                '                        <position x="%s" y="%s" z="%s" />\n' %
                (co[0], co[1], co[2]))
            f.write(
                '                        <normal x="%s" y="%s" z="%s" />\n' %
                (norm[0], norm[1], norm[2]))
            f.write('                    </vertex>\n')
        f.write('                </vertexbuffer>\n')

        loopprog(0.8 - 0.1 * bool(human.getSkeleton()), 0.9,
                 "Writing UVs of %s." % rmesh.name)
        # UV Texture Coordinates
        f.write(
            '                <vertexbuffer texture_coord_dimensions_0="2" texture_coords="1">\n'
        )
        for vIdx in xrange(numVerts):
            if obj.has_uv:
                u, v = obj.r_texco[vIdx]
                v = 1 - v
            else:
                u, v = 0, 0
            f.write('                    <vertex>\n')
            f.write('                        <texcoord u="%s" v="%s" />\n' %
                    (u, v))
            f.write('                    </vertex>\n')
        f.write('                </vertexbuffer>\n')
        f.write('            </geometry>\n')

        if human.getSkeleton():
            loopprog(0.9, 0.99, "Writing bone assignments of %s." % rmesh.name)
        else:
            loopprog(0.99, None, "Written %s." % rmesh.name)
        # Skeleton bone assignments
        if human.getSkeleton():
            bodyWeights = human.getVertexWeights()
            if rmesh.type:
                # Determine vertex weights for proxy
                weights = skeleton.getProxyWeights(rmesh.proxy, bodyWeights,
                                                   obj)
            else:
                # Use vertex weights for human body
                weights = bodyWeights
                # Account for vertices that are filtered out
                if rmesh.vertexMapping != None:
                    filteredVIdxMap = rmesh.vertexMapping
                    weights2 = {}
                    for (boneName, (verts, ws)) in weights.items():
                        verts2 = []
                        ws2 = []
                        for i, vIdx in enumerate(verts):
                            if vIdx in filteredVIdxMap:
                                verts2.append(filteredVIdxMap[vIdx])
                                ws2.append(ws[i])
                        weights2[boneName] = (verts2, ws2)
                    weights = weights2

            # Remap vertex weights to the unwelded vertices of the object (obj.coord to obj.r_coord)
            originalToUnweldedMap = {}
            for unweldedIdx, originalIdx in enumerate(obj.vmap):
                if originalIdx not in originalToUnweldedMap.keys():
                    originalToUnweldedMap[originalIdx] = []
                originalToUnweldedMap[originalIdx].append(unweldedIdx)

            f.write('            <boneassignments>\n')
            boneNames = [bone.name for bone in human.getSkeleton().getBones()]
            for (boneName, (verts, ws)) in weights.items():
                bIdx = boneNames.index(boneName)
                for i, vIdx in enumerate(verts):
                    w = ws[i]
                    try:
                        for r_vIdx in originalToUnweldedMap[vIdx]:
                            f.write(
                                '                <vertexboneassignment vertexindex="%s" boneindex="%s" weight="%s" />\n'
                                % (r_vIdx, bIdx, w))
                    except:
                        # unused coord
                        pass
            f.write('            </boneassignments>\n')

        progress.step()
        f.write('        </submesh>\n')

    f.write('    </submeshes>\n')
    f.write('    <submeshnames>\n')
    for rmeshIdx, rmesh in enumerate(rmeshes):
        f.write('        <submeshname name="%s" index="%s" />\n' %
                (formatName(rmesh.name)
                 if formatName(rmesh.name) != name else "human", rmeshIdx))
    f.write('    </submeshnames>\n')

    if human.getSkeleton():
        f.write('    <skeletonlink name="%s.skeleton" />\n' % name)
    f.write('</mesh>')
    f.close()
Ejemplo n.º 7
0
def writeMeshFile(human, filepath, stuffs, config):
    filename = os.path.basename(filepath)
    name = formatName(config.goodName(os.path.splitext(filename)[0]))

    f = open(filepath, 'w')
    f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
    f.write('<!-- Exported from MakeHuman (www.makehuman.org) -->\n')
    f.write('<mesh>\n')
    f.write('    <submeshes>\n')

    for stuffIdx, stuff in enumerate(stuffs):
        obj = stuff.meshInfo.object
        # Make sure vertex normals are calculated
        obj.calcFaceNormals()
        obj.calcVertexNormals()
        # Calculate rendering data so we can use the unwelded vertices
        obj.updateIndexBuffer()
        numVerts = len(obj.r_coord)
        if obj.vertsPerPrimitive == 4:
            # Quads
            numFaces = len(obj.r_faces) * 2
        else:
            # Tris
            numFaces = len(obj.r_faces)

        f.write('        <submesh material="%s_%s_%s" usesharedvertices="false" use32bitindexes="false" operationtype="triangle_list">\n' % (formatName(name), stuffIdx, formatName(stuff.name) if formatName(stuff.name) != name else "human"))

        # Faces
        f.write('            <faces count="%s">\n' % numFaces)
        for fv in obj.r_faces:
            f.write('                <face v1="%s" v2="%s" v3="%s" />\n' % (fv[0], fv[1], fv[2]))
            if obj.vertsPerPrimitive == 4:
                f.write('                <face v1="%s" v2="%s" v3="%s" />\n' % (fv[2], fv[3], fv[0]))
        f.write('            </faces>\n')

        # Vertices
        f.write('            <geometry vertexcount="%s">\n' % numVerts)
        f.write('                <vertexbuffer positions="true" normals="true">\n')
        #f.write('                <vertexbuffer positions="true">\n')
        for vIdx, co in enumerate(obj.r_coord):
            if feetOnGround:
                co = co.copy()
                co[1] += getFeetOnGroundOffset(human)

            # Note: Ogre3d uses a y-up coordinate system (just like MH)
            norm = obj.r_vnorm[vIdx]
            f.write('                    <vertex>\n')
            f.write('                        <position x="%s" y="%s" z="%s" />\n' % (co[0], co[1], co[2]))
            f.write('                        <normal x="%s" y="%s" z="%s" />\n' % (norm[0], norm[1], norm[2]))
            f.write('                    </vertex>\n')
        f.write('                </vertexbuffer>\n')

        # UV Texture Coordinates
        f.write('                <vertexbuffer texture_coord_dimensions_0="2" texture_coords="1">\n')
        for vIdx in xrange(numVerts): 
            if obj.has_uv:
                u, v = obj.r_texco[vIdx]
                v = 1-v
            else:
                u, v = 0, 0
            f.write('                    <vertex>\n')
            f.write('                        <texcoord u="%s" v="%s" />\n' % (u, v))
            f.write('                    </vertex>\n')
        f.write('                </vertexbuffer>\n')
        f.write('            </geometry>\n')

        # Skeleton bone assignments
        if human.getSkeleton():
            bodyWeights = human.getVertexWeights()
            if stuff.type:
                # Determine vertex weights for proxy
                weights = skeleton.getProxyWeights(stuff.proxy, bodyWeights, obj)
            else:
                # Use vertex weights for human body
                weights = bodyWeights
                # Account for vertices that are filtered out
                if stuff.meshInfo.vertexMapping != None:
                    filteredVIdxMap = stuff.meshInfo.vertexMapping
                    weights2 = {}
                    for (boneName, (verts,ws)) in weights.items():
                        verts2 = []
                        ws2 = []
                        for i, vIdx in enumerate(verts):
                            if vIdx in filteredVIdxMap:
                                verts2.append(filteredVIdxMap[vIdx])
                                ws2.append(ws[i])
                        weights2[boneName] = (verts2, ws2)
                    weights = weights2

            # Remap vertex weights to the unwelded vertices of the object (obj.coord to obj.r_coord)
            originalToUnweldedMap = {}
            for unweldedIdx, originalIdx in enumerate(obj.vmap):
                if originalIdx not in originalToUnweldedMap.keys():
                    originalToUnweldedMap[originalIdx] = []
                originalToUnweldedMap[originalIdx].append(unweldedIdx)

            f.write('            <boneassignments>\n')
            boneNames = [ bone.name for bone in human.getSkeleton().getBones() ]
            for (boneName, (verts,ws)) in weights.items():
                bIdx = boneNames.index(boneName)
                for i, vIdx in enumerate(verts):
                    w = ws[i]
                    try:
                        for r_vIdx in originalToUnweldedMap[vIdx]:
                            f.write('                <vertexboneassignment vertexindex="%s" boneindex="%s" weight="%s" />\n' % (r_vIdx, bIdx, w))
                    except:
                        # unused coord
                        pass
            f.write('            </boneassignments>\n')
        f.write('        </submesh>\n')

    f.write('    </submeshes>\n')
    f.write('    <submeshnames>\n')
    for stuffIdx, stuff in enumerate(stuffs):
        f.write('        <submeshname name="%s" index="%s" />\n' % (formatName(stuff.name) if formatName(stuff.name) != name else "human", stuffIdx))
    f.write('    </submeshnames>\n')

    if human.getSkeleton():
        f.write('    <skeletonlink name="%s.skeleton" />\n' % name)
    f.write('</mesh>')
    f.close()
Ejemplo n.º 8
0
def exportMd5(human, filepath, config):
    """
    This function exports MakeHuman mesh and skeleton data to id Software's MD5 format.

    Parameters
    ----------

    human:
      *Human*.  The object whose information is to be used for the export.
    filepath:
      *string*.  The filepath of the file to export the object to.
    config:
      *Config*.  Export configuration.
    """

    progress = Progress()

    obj = human.meshData
    config.setHuman(human)
    config.zUp = True
    config.feetOnGround = True    # TODO this only works when exporting MHX mesh (a design error in exportutils)
    config.scale = 1
    config.setupTexFolder(filepath)
    filename = os.path.basename(filepath)
    name = config.goodName(os.path.splitext(filename)[0])

    humanBBox = human.meshData.calcBBox()

    progress(0, 0.2, "Collecting Objects")
    rmeshes = exportutils.collect.setupMeshes(
        name,
        human,
        config=config,
        subdivide=config.subdivide)

    if human.getSkeleton():
        numJoints = human.getSkeleton().getBoneCount() +1 # Amount of joints + the hardcoded origin below
    else:
        numJoints = 1

    f = codecs.open(filepath, 'w', encoding="utf-8")
    f.write('MD5Version 10\n')
    f.write('commandline ""\n\n')
    f.write('numJoints %d\n' % numJoints)
    f.write('numMeshes %d\n\n' % (len(rmeshes)))

    f.write('joints {\n')
    # Hardcoded root joint
    f.write('\t"%s" %d ( %f %f %f ) ( %f %f %f )\n' % ('origin', -1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0))
    progress(0.2, 0.3, "Writing Bones")
    if human.getSkeleton():
        bones = human.getSkeleton().getBones()
        boneprog = Progress(len(bones))
        for bone in bones:
            writeBone(f, bone, human, config)
            boneprog.step()
    f.write('}\n\n')

    progress(0.3, 0.8, "Writing Objects")
    loopprog = Progress(len(rmeshes))
    for rmeshIdx, rmesh in enumerate(rmeshes):
        # rmesh.type: None is human, "Proxymeshes" is human proxy, "Clothes" for clothing and "Hair" for hair
        objprog = Progress()

        obj = rmesh.object

        obj.calcFaceNormals()
        obj.calcVertexNormals()
        obj.updateIndexBuffer()

        numVerts = len(obj.r_coord)
        if obj.vertsPerPrimitive == 4:
            # Quads
            numFaces = len(obj.r_faces) * 2
        else:
            # Tris
            numFaces = len(obj.r_faces)

        f.write('mesh {\n')
        mat = rmesh.material
        if mat.diffuseTexture:
            tex = copyTexture(mat.diffuseTexture, human, config)
            f.write('\tshader "%s"\n' % tex)

        f.write('\n\tnumverts %d\n' % numVerts)

        # Collect vertex weights
        if human.getSkeleton():
            objprog(0, 0.2)
            bodyWeights = human.getVertexWeights()

            if rmesh.type:
                # Determine vertex weights for proxy
                weights = skeleton.getProxyWeights(rmesh.proxy, bodyWeights, obj)
            else:
                # Use vertex weights for human body
                weights = bodyWeights
                # Account for vertices that are filtered out
                if rmesh.vertexMapping != None:
                    filteredVIdxMap = rmesh.vertexMapping
                    weights2 = {}
                    for (boneName, (verts,ws)) in weights.items():
                        verts2 = []
                        ws2 = []
                        for i, vIdx in enumerate(verts):
                            if vIdx in filteredVIdxMap:
                                verts2.append(filteredVIdxMap[vIdx])
                                ws2.append(ws[i])
                        weights2[boneName] = (verts2, ws2)
                    weights = weights2

            # Remap vertex weights to the unwelded vertices of the object (obj.coord to obj.r_coord)
            originalToUnweldedMap = {}
            for unweldedIdx, originalIdx in enumerate(obj.vmap):
                if originalIdx not in originalToUnweldedMap.keys():
                    originalToUnweldedMap[originalIdx] = []
                originalToUnweldedMap[originalIdx].append(unweldedIdx)

            # Build a weights list indexed per vertex
            jointIndexes = {}
            jointIndexes['origin'] = 0
            joints = [None] + human.getSkeleton().getBones() # origin joint is None
            for idx,bone in enumerate(joints):
                if bone:
                    jointIndexes[bone.name] = idx
            vertWeights = {}    # = dict( vertIdx: [ (jointIdx1, weight1), ...])
            for (jointName, (verts,ws)) in weights.items():
                jointIdx = jointIndexes[jointName]
                for idx,v in enumerate(verts):
                    try:
                        for r_vIdx in originalToUnweldedMap[v]:
                            if r_vIdx not in vertWeights:
                                vertWeights[r_vIdx] = []
                            vertWeights[r_vIdx].append((jointIdx, ws[idx]))
                    except:
                        # unused coord
                        pass
            for vert in xrange(numVerts):
                if vert not in vertWeights:
                    # Weight vertex completely to origin joint
                    vertWeights[vert] = [(0, 1.0)]
            objprog(0.2, 0.3)
        else:
            vertWeights = None
            objprog(0, 0.3)

        # Write vertices
        wCount = 0
        for vert in xrange(numVerts):
            if obj.has_uv:
                u, v = obj.r_texco[vert]
            else:
                u, v = 0, 0
            if vertWeights == None:
                numWeights = 1
            else:
                numWeights = len(vertWeights[vert])
            # vert [vertIndex] ( [texU] [texV] ) [weightIndex] [weightElem]
            f.write('\tvert %d ( %f %f ) %d %d\n' % (vert, u, 1.0-v, wCount, numWeights))
            wCount = wCount + numWeights
        objprog(0.3, 0.5)

        # Write faces
        f.write('\n\tnumtris %d\n' % numFaces)
        fn = 0
        for fv in obj.r_faces:
            # tri [triIndex] [vertIndex1] [vertIndex2] [vertIndex3]
            f.write('\ttri %d %d %d %d\n' % (fn, fv[2], fv[1], fv[0]))
            fn += 1
            if fv[0] != fv[3]:
                f.write('\ttri %d %d %d %d\n' % (fn, fv[0], fv[3], fv[2]))
                fn += 1
        objprog(0.5, 0.99)

        # Write bone weighting
        bwprog = Progress(len(obj.r_coord)).HighFrequency(200)
        if human.getSkeleton():
            f.write('\n\tnumweights %d\n' % wCount)
            wCount = 0
            for idx,co in enumerate(obj.r_coord):
                for (jointIdx, jointWght) in vertWeights[idx]:
                    # Get vertex position in bone space
                    if joints[jointIdx]:
                        invbonematrix = joints[jointIdx].matRestGlobal.copy()
                        invbonematrix[:3,3] = [0,0,0]
                        invbonematrix = la.inv(invbonematrix)
                        relPos = np.ones(4, dtype=np.float32)
                        relPos[:3] = co[:3]
                        relPos[:3] -= joints[jointIdx].getRestHeadPos()
                        relPos[:3] *= scale
                        #relPos = np.dot(relPos, invbonematrix)
                    else:
                        relPos = co[:3] * scale

                    if config.zUp:
                        relPos[:3] = relPos[[0,2,1]] * [1,-1,1]

                    # weight [weightIndex] [jointIndex] [weightValue] ( [xPos] [yPos] [zPos] )
                    f.write('\tweight %d %d %f ( %f %f %f )\n' % (wCount, jointIdx, jointWght, relPos[0], relPos[1], relPos[2]))
                    wCount = wCount +1
                bwprog.step()
        else:
            # No skeleton selected: Attach all vertices to the root with weight 1.0
            f.write('\n\tnumweights %d\n' % (numVerts))
            for idx,co in enumerate(obj.r_coord):
                # weight [weightIndex] [jointIndex] [weightValue] ( [xPos] [yPos] [zPos] )
                co = co.copy() * scale

                if config.feetOnGround:
                    co[1] += (getFeetOnGroundOffset(human) * scale)

                if config.zUp:
                    co = co[[0,2,1]] * [1,-1,1]

                f.write('\tweight %d %d %f ( %f %f %f )\n' % (idx, 0, 1.0, co[0], co[1], co[2]))
                # Note: MD5 has a z-up coordinate system
                bwprog.step()
        f.write('}\n\n')
        loopprog.step()
    f.close()

    progress(0.8, 0.99, "Writing Animations")
    if human.getSkeleton() and hasattr(human, 'animations'):
        animprog = Progress(len(human.animations))
        for anim in human.animations:
            writeAnimation(filepath, human, humanBBox, config, anim.getAnimationTrack())
            animprog.step()

    progress(1, None, "MD5 export finished. Exported file: %s" % filepath)
Ejemplo n.º 9
0
def exportFbx(filepath, config):
    from armature.armature import setupArmature

    G.app.progress(0, text="Preparing")

    human = config.human
    config.setupTexFolder(filepath)

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

    filename = os.path.basename(filepath)
    name = config.goodName(os.path.splitext(filename)[0])
    #rawTargets = exportutils.collect.readTargets(human, config)    # TODO no idea what to do with this

    # Collect objects, scale meshes and filter out hidden faces/verts, scale rig
    objects = human.getObjects(excludeZeroFaceObjs=True)
    meshes = [obj.mesh.clone(config.scale, True) for obj in objects]
    skel = human.getSkeleton()
    if skel:
        skel = skel.scaled(config.scale)

    # Set mesh names
    for mesh in meshes:
        mesh.name = fbx_utils.getMeshName(mesh, skel)

    G.app.progress(0.5, text="Exporting %s" % filepath)

    fp = codecs.open(filepath, "w", encoding="utf-8")
    fbx_utils.resetId()  # Reset global ID generator
    fbx_utils.setAbsolutePath(filepath)
    fbx_header.writeHeader(fp, filepath)

    # Generate bone weights for all meshes up front so they can be reused for all
    if skel:
        rawWeights = human.getVertexWeights()  # Basemesh weights
        for mesh in meshes:
            if mesh.object.proxy:
                # Transfer weights to proxy
                parentWeights = skeleton.getProxyWeights(
                    mesh.object.proxy, rawWeights)
            else:
                parentWeights = rawWeights
            # Transfer weights to face/vert masked and/or subdivided mesh
            weights = mesh.getWeights(parentWeights)

            # Attach these vertexWeights to the mesh to pass them around the
            # exporter easier, the cloned mesh is discarded afterwards, anyway
            mesh.vertexWeights = weights
    else:
        # Attach trivial weights to the meshes
        for mesh in meshes:
            mesh.vertexWeights = dict()

    # TODO if "shapes" need to be exported, attach them to meshes in a similar way

    nVertexGroups, nShapes = fbx_deformer.getObjectCounts(meshes)
    fbx_header.writeObjectDefs(fp, meshes, skel, config)
    fbx_skeleton.writeObjectDefs(fp, meshes, skel)
    fbx_mesh.writeObjectDefs(fp, meshes, nShapes)
    fbx_deformer.writeObjectDefs(fp, meshes, skel)
    if config.useMaterials:
        fbx_material.writeObjectDefs(fp, meshes)
    #fbx_anim.writeObjectDefs(fp)
    fp.write('}\n\n')

    fbx_header.writeObjectProps(fp)
    if skel:
        fbx_skeleton.writeObjectProps(fp, skel, config)
    fbx_mesh.writeObjectProps(fp, meshes, config)
    fbx_deformer.writeObjectProps(fp, meshes, skel, config)
    if config.useMaterials:
        fbx_material.writeObjectProps(fp, meshes, config)
    #fbx_anim.writeObjectProps(fp)
    fp.write('}\n\n')

    fbx_utils.startLinking()
    fbx_header.writeLinks(fp)
    if skel:
        fbx_skeleton.writeLinks(fp, skel)
    fbx_mesh.writeLinks(fp, meshes)
    fbx_deformer.writeLinks(fp, meshes, skel)
    if config.useMaterials:
        fbx_material.writeLinks(fp, meshes)
    #fbx_anim.writeLinks(fp)
    fp.write('}\n\n')

    fbx_header.writeTakes(fp)
    fp.close()

    G.app.progress(1)
    log.message("%s written" % filepath)
Ejemplo n.º 10
0
def writeMeshFile(human, filepath, objects, config):
    progress = Progress(len(objects))

    filename = os.path.basename(filepath)
    name = formatName(os.path.splitext(filename)[0])

    f = codecs.open(filepath, 'w', encoding="utf-8")
    lines = []
    lines.append('<?xml version="1.0" encoding="UTF-8"?>')
    lines.append('<!-- Exported from MakeHuman (www.makehuman.org) -->')
    lines.append('<mesh>')
    lines.append('    <submeshes>')

    for objIdx, obj in enumerate(objects):
        loopprog = Progress()

        loopprog(0.0, 0.1, "Writing %s mesh.", obj.name)

        pxy = obj.proxy
        mesh = obj.mesh

        # Scale and filter out masked vertices/faces
        mesh = mesh.clone(scale=config.scale, filterMaskedVerts=True
                          )  # here obj.parent is set to the original obj

        numVerts = len(mesh.r_coord)

        if mesh.vertsPerPrimitive == 4:
            # Quads
            numFaces = len(mesh.r_faces) * 2
        else:
            # Tris
            numFaces = len(mesh.r_faces)

        loopprog(0.1, 0.3, "Writing faces of %s.", obj.name)
        # TODO add proxy type name in material name as well
        lines.append(
            '        <submesh material="%s_%s_%s" usesharedvertices="false" use32bitindexes="false" operationtype="triangle_list">'
            % (formatName(name), objIdx, formatName(obj.name)
               if formatName(obj.name) != name else "human"))

        # Faces
        lines.append('            <faces count="%s">' % numFaces)
        if mesh.vertsPerPrimitive == 4:
            lines.extend( ['''\
                <face v1="%s" v2="%s" v3="%s" />
                <face v1="%s" v2="%s" v3="%s" />''' % (fv[0], fv[1], fv[2],
                                                       fv[2], fv[3], fv[0]) \
                for fv in mesh.r_faces ] )
        else:
            lines.extend([
                '                <face v1="%s" v2="%s" v3="%s" />' %
                (fv[0], fv[1], fv[2]) for fv in mesh.r_faces
            ])
        lines.append('            </faces>')

        loopprog(0.3, 0.7, "Writing vertices of %s.", obj.name)
        # Vertices
        lines.append('            <geometry vertexcount="%s">' % numVerts)
        lines.append(
            '                <vertexbuffer positions="true" normals="true">')
        coords = mesh.r_coord.copy()
        if config.feetOnGround:
            coords[:, 1] += getFeetOnGroundOffset(config)
        # Note: Ogre3d uses a y-up coordinate system (just like MH)
        lines.extend(['''\
                    <vertex>
                        <position x="%s" y="%s" z="%s" />
                        <normal x="%s" y="%s" z="%s" />
                    </vertex>''' % (coords[vIdx,0], coords[vIdx,1], coords[vIdx,2],
                                    mesh.r_vnorm[vIdx,0], mesh.r_vnorm[vIdx,1], mesh.r_vnorm[vIdx,2]) \
            for vIdx in xrange(coords.shape[0]) ])
        lines.append('                </vertexbuffer>')

        loopprog(0.8 - 0.1 * bool(human.getSkeleton()), 0.9,
                 "Writing UVs of %s.", obj.name)
        # UV Texture Coordinates
        lines.append(
            '                <vertexbuffer texture_coord_dimensions_0="2" texture_coords="1">'
        )
        if mesh.has_uv:
            uvs = mesh.r_texco.copy()
            uvs[:, 1] = 1 - uvs[:, 1]  # v = 1 - v
        else:
            uvs = np.zeros((numVerts, 2), dtype=np.float32)

        lines.extend([
            '''\
                    <vertex>
                        <texcoord u="%s" v="%s" />
                    </vertex>''' % (u, v) for u, v in uvs
        ])
        lines.append('                </vertexbuffer>')
        lines.append('            </geometry>')

        if human.getSkeleton():
            loopprog(0.9, 0.99, "Writing bone assignments of %s.", obj.name)
        else:
            loopprog(0.99, None, "Written %s.", obj.name)

        # Skeleton bone assignments
        if human.getSkeleton():
            # TODO getVertexWeights is the best name for this, use it consistently in proxy/module3d
            bodyWeights = human.getVertexWeights()
            if pxy:
                # Determine vertex weights for proxy (map to unfiltered proxy mesh)
                weights = skeleton.getProxyWeights(pxy, bodyWeights)
            else:
                # Use vertex weights for human body
                weights = bodyWeights

            # Remap vertex weights to account for hidden vertices that are
            # filtered out, and remap to multiple vertices if mesh is subdivided
            weights = mesh.getWeights(weights)

            # Remap vertex weights to the unwelded vertices of the object (mesh.coord to mesh.r_coord)
            originalToUnweldedMap = mesh.inverse_vmap

            lines.append('            <boneassignments>')
            boneNames = [bone.name for bone in human.getSkeleton().getBones()]
            for (boneName, (verts, ws)) in weights.items():
                bIdx = boneNames.index(boneName)
                for i, vIdx in enumerate(verts):
                    w = ws[i]
                    try:
                        lines.extend([
                            '                <vertexboneassignment vertexindex="%s" boneindex="%s" weight="%s" />'
                            % (r_vIdx, bIdx, w)
                            for r_vIdx in originalToUnweldedMap[vIdx]
                        ])
                    except:
                        # unused coord
                        pass
            lines.append('            </boneassignments>')

        progress.step()
        lines.append('        </submesh>')

    lines.append('    </submeshes>')
    lines.append('    <submeshnames>')
    for objIdx, obj in enumerate(objects):
        lines.append(
            '        <submeshname name="%s" index="%s" />' %
            (formatName(obj.name) if formatName(obj.name) != name else "human",
             objIdx))
    lines.append('    </submeshnames>')

    if human.getSkeleton():
        lines.append('    <skeletonlink name="%s.skeleton" />' % name)
    lines.append('</mesh>')

    f.write("\n".join(lines))
    f.close()
Ejemplo n.º 11
0
def writeSkinController(fp, human, mesh, skel, config):
    """
    Write controller for skinning or rigging, in other words: the controller
    that ties an animation skeleton to the mesh.
    """
    progress = Progress()
    progress(0, 0.1)

    nVerts = len(mesh.coord)
    nBones = len(skel.getBones())

    rawWeights = human.getVertexWeights()

    obj = mesh.object

    # Remap vertex weights to mesh
    if obj.proxy:
        import skeleton
        parentWeights = skeleton.getProxyWeights(obj.proxy, rawWeights)
    else:
        parentWeights = rawWeights
    weights = mesh.getWeights(parentWeights)

    vertexWeights = [list() for _ in xrange(nVerts)]
    skinWeights = []
    wn = 0
    boneNames = [bone.name for bone in skel.getBones()]
    for bIdx, boneName in enumerate(boneNames):
        try:
            (verts, ws) = weights[boneName]
        except:
            (verts, ws) = ([], [])
        wts = zip(verts, ws)
        skinWeights += wts
        for (vn, _w) in wts:
            vertexWeights[int(vn)].append((bIdx, wn))
            wn += 1
    nSkinWeights = len(skinWeights)

    # Write rig transform matrix
    progress(0.1, 0.2)
    fp.write('\n' + '    <controller id="%s-skin">\n' % mesh.name +
             '      <skin source="#%sMesh">\n' % mesh.name +
             '        <bind_shape_matrix>\n' + '          1 0 0 0\n' +
             '          0 1 0 0\n' + '          0 0 1 0\n' +
             '          0 0 0 1\n' + '        </bind_shape_matrix>\n' +
             '        <source id="%s-skin-joints">\n' % mesh.name +
             '          <IDREF_array count="%d" id="%s-skin-joints-array">\n' %
             (nBones, mesh.name) + '           ')

    # Write bones
    for bone in skel.getBones():
        bname = goodBoneName(bone.name)
        fp.write(' %s' % bname)

    progress(0.2, 0.4)
    fp.write(
        '\n' + '          </IDREF_array>\n' +
        '          <technique_common>\n' +
        '            <accessor count="%d" source="#%s-skin-joints-array" stride="1">\n'
        % (nBones, mesh.name) +
        '              <param type="IDREF" name="JOINT"></param>\n' +
        '            </accessor>\n' + '          </technique_common>\n' +
        '        </source>\n' +
        '        <source id="%s-skin-weights">\n' % mesh.name +
        '          <float_array count="%d" id="%s-skin-weights-array">\n' %
        (nSkinWeights, mesh.name) + '           ')

    fp.write(' '.join('%s' % w[1] for w in skinWeights))

    fp.write(
        '\n' + '          </float_array>\n' +
        '          <technique_common>\n' +
        '            <accessor count="%d" source="#%s-skin-weights-array" stride="1">\n'
        % (nSkinWeights, mesh.name) +
        '              <param type="float" name="WEIGHT"></param>\n' +
        '            </accessor>\n' + '          </technique_common>\n' +
        '        </source>\n' +
        '        <source id="%s-skin-poses">\n' % mesh.name +
        '          <float_array count="%d" id="%s-skin-poses-array">' %
        (16 * nBones, mesh.name))

    progress(0.4, 0.6)
    for bone in skel.getBones():
        #mat = la.inv(bone.getRestOrTPoseMatrix(config))    # TODO remove (this is a hack)
        mat = la.inv(
            bone.getRestMatrix(config.meshOrientation, config.localBoneAxis,
                               config.offset))
        for i in range(4):
            fp.write('\n           ')
            for j in range(4):
                fp.write(' %.4f' % mat[i, j])
        fp.write('\n')

    progress(0.6, 0.8)
    fp.write(
        '\n' + '          </float_array>\n' +
        '          <technique_common>\n' +
        '            <accessor count="%d" source="#%s-skin-poses-array" stride="16">\n'
        % (nBones, mesh.name) +
        '              <param type="float4x4"></param>\n' +
        '            </accessor>\n' + '          </technique_common>\n' +
        '        </source>\n' + '        <joints>\n' +
        '          <input semantic="JOINT" source="#%s-skin-joints"/>\n' %
        mesh.name +
        '          <input semantic="INV_BIND_MATRIX" source="#%s-skin-poses"/>\n'
        % mesh.name + '        </joints>\n' +
        '        <vertex_weights count="%d">\n' % nVerts +
        '          <input offset="0" semantic="JOINT" source="#%s-skin-joints"/>\n'
        % mesh.name +
        '          <input offset="1" semantic="WEIGHT" source="#%s-skin-weights"/>\n'
        % mesh.name + '          <vcount>\n' + '            ')

    # Write number of bones weighted per vertex
    fp.write(' '.join(['%d' % len(wts) for wts in vertexWeights]))

    progress(0.8, 0.99)
    fp.write('\n' + '          </vcount>\n' '          <v>\n' + '           ')

    for wts in vertexWeights:
        fp.write(''.join([' %d %d' % pair for pair in wts]))

    fp.write('\n' + '          </v>\n' + '        </vertex_weights>\n' +
             '      </skin>\n' + '    </controller>\n')

    progress(1)
Ejemplo n.º 12
0
def writeMeshFile(human, filepath, meshes, config):
    progress = Progress(len(meshes))

    filename = os.path.basename(filepath)
    name = formatName(os.path.splitext(filename)[0])

    f = codecs.open(filepath, 'w', encoding="utf-8")
    lines = []
    lines.append('<?xml version="1.0" encoding="UTF-8"?>')
    lines.append('<!-- Exported from MakeHuman (www.makehuman.org) -->')
    lines.append('<mesh>')
    lines.append('    <submeshes>')

    for objIdx, mesh in enumerate(meshes):
        loopprog = Progress()

        loopprog(0.0, 0.1, "Writing %s mesh.", mesh.name)

        if isinstance(mesh, proxy.Proxy):
            # Object is proxy
            pxy = mesh
            obj = pxy.object.mesh
        else:
            # Object is human mesh
            pxy = mesh.proxy
            obj = mesh.mesh

        # Scale and filter out masked vertices/faces
        obj = obj.clone(scale=1, filterMaskedVerts=True)  # here obj.parent is set to the original obj

        numVerts = len(obj.r_coord)

        if obj.vertsPerPrimitive == 4:
            # Quads
            numFaces = len(obj.r_faces) * 2
        else:
            # Tris
            numFaces = len(obj.r_faces)

        loopprog(0.1, 0.3, "Writing faces of %s.", obj.name)
        # TODO add proxy type name in material name as well
        lines.append('        <submesh material="%s_%s_%s" usesharedvertices="false" use32bitindexes="false" operationtype="triangle_list">' % (formatName(name), objIdx, formatName(obj.name) if formatName(obj.name) != name else "human"))

        # Faces
        lines.append('            <faces count="%s">' % numFaces)
        if obj.vertsPerPrimitive == 4:
            lines.extend( ['''\
                <face v1="%s" v2="%s" v3="%s" />
                <face v1="%s" v2="%s" v3="%s" />''' % (fv[0], fv[1], fv[2],
                                                       fv[2], fv[3], fv[0]) \
                for fv in obj.r_faces ] )
        else:
            lines.extend( ['                <face v1="%s" v2="%s" v3="%s" />' % (fv[0], fv[1], fv[2]) for fv in obj.r_faces])
        lines.append('            </faces>')

        loopprog(0.3, 0.7, "Writing vertices of %s.", obj.name)
        # Vertices
        lines.append('            <geometry vertexcount="%s">' % numVerts)
        lines.append('                <vertexbuffer positions="true" normals="true">')
        coords = obj.r_coord.copy()
        if config.feetOnGround:
            coords[:,1] += getFeetOnGroundOffset(human)
        # Note: Ogre3d uses a y-up coordinate system (just like MH)
        lines.extend(['''\
                    <vertex>
                        <position x="%s" y="%s" z="%s" />
                        <normal x="%s" y="%s" z="%s" />
                    </vertex>''' % (coords[vIdx,0], coords[vIdx,1], coords[vIdx,2],
                                    obj.r_vnorm[vIdx,0], obj.r_vnorm[vIdx,1], obj.r_vnorm[vIdx,2]) \
            for vIdx in xrange(coords.shape[0]) ])
        lines.append('                </vertexbuffer>')


        loopprog(0.8 - 0.1*bool(human.getSkeleton()), 0.9, "Writing UVs of %s.", obj.name)
        # UV Texture Coordinates
        lines.append('                <vertexbuffer texture_coord_dimensions_0="2" texture_coords="1">')
        if obj.has_uv:
            uvs = obj.r_texco.copy()
            uvs[:,1] = 1-uvs[:,1]  # v = 1 - v
        else:
            uvs = np.zeros((numVerts,2), dtype=np.float32)

        lines.extend( ['''\
                    <vertex>
                        <texcoord u="%s" v="%s" />
                    </vertex>''' % (u, v) for u, v in uvs ] )
        lines.append('                </vertexbuffer>')
        lines.append('            </geometry>')

        if human.getSkeleton():
            loopprog(0.9, 0.99, "Writing bone assignments of %s.", obj.name)
        else:
            loopprog(0.99, None, "Written %s.", obj.name)

        # Skeleton bone assignments
        if human.getSkeleton():
            bodyWeights = human.getVertexWeights()
            if pxy:
                # Determine vertex weights for proxy (map to unfiltered proxy mesh)
                weights = skeleton.getProxyWeights(pxy, bodyWeights, obj.parent)
            else:
                # Use vertex weights for human body
                weights = bodyWeights

            # Account for vertices that are filtered out
            filteredVIdxMap = obj.inverse_parent_map

            # Remap vertex weights to the unwelded vertices of the object (obj.coord to obj.r_coord)
            originalToUnweldedMap = obj.inverse_vmap

            lines.append('            <boneassignments>')
            boneNames = [ bone.name for bone in human.getSkeleton().getBones() ]
            for (boneName, (verts,ws)) in weights.items():
                bIdx = boneNames.index(boneName)
                for i, vIdx in enumerate(verts):
                    if filteredVIdxMap[vIdx] >= 0:
                        # Vertex for weight is included in the filtered mesh
                        vIdx = filteredVIdxMap[vIdx]
                        w = ws[i]
                        try:
                            lines.extend( ['                <vertexboneassignment vertexindex="%s" boneindex="%s" weight="%s" />' % (r_vIdx, bIdx, w)
                                            for r_vIdx in originalToUnweldedMap[vIdx]] )
                        except:
                            # unused coord
                            pass
            lines.append('            </boneassignments>')

        progress.step()
        lines.append('        </submesh>')

    lines.append('    </submeshes>')
    lines.append('    <submeshnames>')
    for objIdx, mesh in enumerate(meshes):
        # TODO this isinstance test everytime is a hassle, perhaps getMeshes() can return meshes in nicer form
        if isinstance(mesh, proxy.Proxy):
            # Object is proxy
            obj = mesh.object.mesh
        else:
            # Object is human mesh
            obj = mesh.mesh
        lines.append('        <submeshname name="%s" index="%s" />' % (formatName(obj.name) if formatName(obj.name) != name else "human", objIdx))
    lines.append('    </submeshnames>')

    if human.getSkeleton():
        lines.append('    <skeletonlink name="%s.skeleton" />' % name)
    lines.append('</mesh>')

    f.write("\n".join(lines))
    f.close()