Ejemplo n.º 1
0
def exportOgreMesh(human, filepath, config, progressCallback=None):
    progress = Progress.begin(logging=True, timing=True)

    progress(0, 0.05, "Setting properties")
    config.setHuman(human)
    feetOnGround = config.feetOnGround
    config.feetOnGround = False
    # TODO account for config.scale in skeleton
    config.setupTexFolder(filepath)
    filename = os.path.basename(filepath)
    name = formatName(config.goodName(os.path.splitext(filename)[0]))

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

    config.feetOnGround = feetOnGround

    progress(0.2, 0.95 - 0.35 * bool(human.getSkeleton()))
    writeMeshFile(human, filepath, rmeshes, config)
    if human.getSkeleton():
        progress(0.6, 0.95, "Writing Skeleton")
        writeSkeletonFile(human, filepath, config)
    progress(0.95, 0.99, "Writing Materials")
    writeMaterialFile(human, filepath, rmeshes, config)
    progress(1.0, None, "Ogre export finished.")
Ejemplo n.º 2
0
    def export(self, human, filename):
        from . import mh2md5
        cfg = MD5Config(self)
        cfg.selectedOptions(self)

        progress = Progress.begin() (0, 1)
        mh2md5.exportMd5(human, filename("md5mesh"), cfg)
Ejemplo n.º 3
0
def exportOgreMesh(filepath, config):
    progress = Progress.begin()

    progress(0, 0.05, "Setting properties")  # TODO this leads to a disastrous amount of confusion among translators 
    human = config.human
    feetOnGround = config.feetOnGround  # TODO this is probably not even worth an option, always feet on ground should be a good default
    config.feetOnGround = False
    # TODO account for config.scale in skeleton
    config.setupTexFolder(filepath) # TODO unused
    filename = os.path.basename(filepath)
    name = formatName(os.path.splitext(filename)[0])

    progress(0.05, 0.2, "Collecting Objects")
    meshes = human.getMeshes()

    config.feetOnGround = feetOnGround

    progress(0.2, 0.95 - 0.35*bool(human.getSkeleton()))
    writeMeshFile(human, filepath, meshes, config)
    if human.getSkeleton():
        progress(0.6, 0.95, "Writing Skeleton")
        writeSkeletonFile(human, filepath, config)
    progress(0.95, 0.99, "Writing Materials")
    writeMaterialFile(human, filepath, meshes, config)
    progress(1.0, None, "Ogre export finished.")
Ejemplo n.º 4
0
    def export(self, human, filename):
        reload(mh2md5)
        cfg = self.getConfig()
        cfg.setHuman(human)

        progress = Progress.begin()(0, 1)
        mh2md5.exportMd5(filename("md5mesh"), cfg)
Ejemplo n.º 5
0
    def export(self, human, filename):
        reload(mh2md5)
        cfg = self.getConfig()
        cfg.setHuman(human)

        progress = Progress.begin() (0, 1)
        mh2md5.exportMd5(filename("md5mesh"), cfg)
Ejemplo n.º 6
0
    def export(self, human, filename):
        from progress import Progress
        from . import mh2obj

        progress = Progress.begin() (0, 1)
        cfg = self.getConfig()
        cfg.setHuman(human)
        mh2obj.exportObj(filename("obj"), cfg)
Ejemplo n.º 7
0
    def export(self, human, filename):
        from progress import Progress
        from . import mh2obj

        progress = Progress.begin() (0, 1)
        cfg = self.getConfig()
        cfg.setHuman(human)
        mh2obj.exportObj(filename("obj"), cfg)
Ejemplo n.º 8
0
    def export(self, human, filename):
        from . import mh2stl
        from progress import Progress
        progress = Progress.begin()(0, 1)

        if self.stlAscii.selected:
            mh2stl.exportStlAscii(human, filename("stl"), STLConfig(self))
        else:
            mh2stl.exportStlBinary(human, filename("stl"), STLConfig(self))
Ejemplo n.º 9
0
    def export(self, human, filename):
        from . import mh2stl
        from progress import Progress
        progress = Progress.begin() (0, 1)

        cfg = self.getConfig()
        cfg.setHuman(human)
        if self.stlAscii.selected:
            mh2stl.exportStlAscii(filename("stl"), cfg)
        else:
            mh2stl.exportStlBinary(filename("stl"), cfg)
Ejemplo n.º 10
0
    def export(self, human, filename):
        from . import mh2stl
        from progress import Progress
        progress = Progress.begin()(0, 1)

        cfg = self.getConfig()
        cfg.setHuman(human)
        if self.stlAscii.selected:
            mh2stl.exportStlAscii(filename("stl"), cfg)
        else:
            mh2stl.exportStlBinary(filename("stl"), cfg)
Ejemplo n.º 11
0
    def export(self, human, filename):
        from . import mh2stl
        from progress import Progress
        progress = Progress.begin() (0, 1)

        cfg = self.getConfig()
        cfg.setHuman(human)
        if self.stlAscii.selected:
            try:
                mh2stl.exportStlAscii(filename("stl"), cfg)
            except MemoryError:
                log.error("Not enough memory to export the mesh. Try exporting a binary STL or disable mesh smoothing.")
        else:
            mh2stl.exportStlBinary(filename("stl"), cfg)
Ejemplo n.º 12
0
    def export(self, human, filename):
        from . import mh2stl
        from progress import Progress
        progress = Progress.begin() (0, 1)

        cfg = self.getConfig()
        cfg.setHuman(human)
        if not self.stlBinary.selected:
            try:
                mh2stl.exportStlAscii(filename("stl"), cfg)
            except MemoryError:
                log.error("Not enough memory to export the mesh. Try exporting a binary STL or disable mesh smoothing.")
        else:
            mh2stl.exportStlBinary(filename("stl"), cfg)
Ejemplo n.º 13
0
def exportOgreMesh(filepath, config):
    progress = Progress.begin()

    progress(0, 0.05, "Preparing export")
    human = config.human

    # TODO account for config.scale in skeleton
    config.setupTexFolder(filepath)  # TODO unused

    progress(0.05, 0.2, "Collecting Objects")
    objects = human.getObjects(excludeZeroFaceObjs=True)

    progress(0.2, 0.95 - 0.35 * bool(human.getSkeleton()))
    writeMeshFile(human, filepath, objects, config)
    if human.getSkeleton():
        progress(0.6, 0.95, "Writing Skeleton")
        writeSkeletonFile(human, filepath, config)
    progress(0.95, 0.99, "Writing Materials")
    writeMaterialFile(human, filepath, objects, config)
    progress(1.0, None, "Ogre export finished.")
def exportOgreMesh(filepath, config):
    progress = Progress.begin()

    progress(0, 0.05, "Preparing export")
    human = config.human

    # TODO account for config.scale in skeleton
    config.setupTexFolder(filepath) # TODO unused

    progress(0.05, 0.2, "Collecting Objects")
    objects = human.getObjects(excludeZeroFaceObjs=True)

    progress(0.2, 0.95 - 0.35*bool(human.getSkeleton()))
    writeMeshFile(human, filepath, objects, config)
    if human.getSkeleton():
        progress(0.6, 0.95, "Writing Skeleton")
        writeSkeletonFile(human, filepath, config)
    progress(0.95, 0.99, "Writing Materials")
    writeMaterialFile(human, filepath, objects, config)
    progress(1.0, None, "Ogre export finished.")
Ejemplo n.º 15
0
def exportOgreMesh(filepath, config):
    progress = Progress.begin()

    progress(0, 0.05, "Setting properties")  # TODO this leads to a disastrous amount of confusion among translators 
    human = config.human

    # TODO account for config.scale in skeleton
    config.setupTexFolder(filepath) # TODO unused

    progress(0.05, 0.2, "Collecting Objects")
    objects = human.getObjects(excludeZeroFaceObjs=True)

    progress(0.2, 0.95 - 0.35*bool(human.getSkeleton()))
    writeMeshFile(human, filepath, objects, config)
    if human.getSkeleton():
        progress(0.6, 0.95, "Writing Skeleton")
        writeSkeletonFile(human, filepath, config)
    progress(0.95, 0.99, "Writing Materials")
    writeMaterialFile(human, filepath, objects, config)
    progress(1.0, None, "Ogre export finished.")
Ejemplo n.º 16
0
def exportOgreMesh(filepath, config):
    progress = Progress.begin()

    progress(
        0, 0.05, "Setting properties"
    )  # TODO this leads to a disastrous amount of confusion among translators
    human = config.human

    # TODO account for config.scale in skeleton
    config.setupTexFolder(filepath)  # TODO unused

    progress(0.05, 0.2, "Collecting Objects")
    objects = human.getObjects(excludeZeroFaceObjs=True)

    progress(0.2, 0.95 - 0.35 * bool(human.getSkeleton()))
    writeMeshFile(human, filepath, objects, config)
    if human.getSkeleton():
        progress(0.6, 0.95, "Writing Skeleton")
        writeSkeletonFile(human, filepath, config)
    progress(0.95, 0.99, "Writing Materials")
    writeMaterialFile(human, filepath, objects, config)
    progress(1.0, None, "Ogre export finished.")
Ejemplo n.º 17
0
    def export(self, human, filename):
        from progress import Progress
        from . import mh2obj

        progress = Progress.begin()(0, 1)
        mh2obj.exportObj(human, filename("obj"), ObjConfig(self))
Ejemplo n.º 18
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.º 19
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
    config.setupTexFolder(filepath)
    filename = os.path.basename(filepath)
    name = config.goodName(os.path.splitext(filename)[0])

    # TODO this should probably be the only option
    config.zUp = True
    config.feetOnGround = True
    config.scale = 5  # Override scale setting to a sensible default for doom-style engines

    humanBBox = human.meshData.calcBBox()

    objects = human.getObjects(excludeZeroFaceObjs=True)
    meshes = [obj.mesh.clone(config.scale, True) for obj in objects]
    # TODO set good names for meshes

    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(meshes)))

    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(meshes))
    for meshIdx, mesh in enumerate(meshes):
        objprog = Progress()
        objprog(0.0, 0.1, "Writing %s mesh." % mesh.name)

        obj = mesh.object

        # Make sure r_... members are initiated
        mesh.updateIndexBuffer()

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

        f.write('mesh {\n')
        mat = mesh.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")
            rawWeights = human.getVertexWeights()

            # Remap vertex weights to mesh
            if obj.proxy:
                # Determine vertex weights for proxy
                parentWeights = obj.proxy.getVertexWeights(rawWeights)
            else:
                parentWeights = rawWeights
            # Account for vertices that are filtered out
            weights = mesh.getVertexWeights(parentWeights)

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

            # Build a weights list indexed per vertex  # TODO this can be done easier by compiling VertexBoneWeights data
            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.data.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." % mesh.name)
        # Write vertices
        wCount = 0
        for vert in xrange(numVerts):
            if mesh.has_uv:
                u, v = mesh.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." % mesh.name)
        # Write faces
        f.write('\n\tnumtris %d\n' % numFaces)
        fn = 0
        for fv in mesh.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." % mesh.name)
        # Write bone weighting
        bwprog = Progress(len(mesh.r_coord)).HighFrequency(200)
        if human.getSkeleton():
            f.write('\n\tnumweights %d\n' % wCount)
            wCount = 0
            for idx,co in enumerate(mesh.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] *= config.scale
                        #relPos = np.dot(relPos, invbonematrix)
                    else:
                        relPos = co[:3] * config.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(mesh.r_coord):
                # weight [weightIndex] [jointIndex] [weightValue] ( [xPos] [yPos] [zPos] )
                co = co.copy()

                if config.feetOnGround:
                    co += config.offset

                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.º 20
0
def Render(settings):
    progress = Progress.begin()

    if not mh.hasRenderToRenderbuffer():
        settings['dimensions'] = (G.windowWidth, G.windowHeight)

    if settings['lightmapSSS']:
        progress(0, 0.05, "Storing data")
        import material
        human = G.app.selectedHuman
        materialBackup = material.Material(human.material)

        progress(0.05, 0.1, "Projecting lightmaps")
        diffuse = imgop.Image(data=human.material.diffuseTexture)
        lmap = projection.mapSceneLighting(settings['scene'],
                                           border=human.material.sssRScale)
        progress(0.1, 0.4, "Applying medium scattering")
        lmapG = imgop.blurred(lmap, human.material.sssGScale, 13)
        progress(0.4, 0.7, "Applying high scattering")
        lmapR = imgop.blurred(lmap, human.material.sssRScale, 13)
        lmap = imgop.compose([lmapR, lmapG, lmap])
        if not diffuse.isEmpty:
            progress(0.7, 0.8, "Combining textures")
            lmap = imgop.resized(lmap,
                                 diffuse.width,
                                 diffuse.height,
                                 filter=image.FILTER_BILINEAR)
            progress(0.8, 0.9)
            lmap = imgop.multiply(lmap, diffuse)
        lmap.sourcePath = "Internal_Renderer_Lightmap_SSS_Texture"

        progress(0.9, 0.95, "Setting up renderer")
        human.material.diffuseTexture = lmap
        human.configureShading(diffuse=True)
        human.shadeless = True
        progress(0.95, 0.98, None)
    else:
        progress(0, 0.99, None)

    if not mh.hasRenderToRenderbuffer():
        # Limited fallback mode, read from screen buffer
        log.message("Fallback render: grab screen")
        img = mh.grabScreen(0, 0, G.windowWidth, G.windowHeight)
        alphaImg = None
    else:
        # Render to framebuffer object
        renderprog = Progress()
        renderprog(0, 0.99 - 0.59 * settings['AA'], "Rendering")
        width, height = settings['dimensions']
        log.message("Rendering at %sx%s", width, height)
        if settings['AA']:
            width = width * 2
            height = height * 2
        img = mh.renderToBuffer(width, height)
        alphaImg = mh.renderAlphaMask(width, height)
        img = imgop.addAlpha(img, imgop.getChannel(alphaImg, 0))

        if settings['AA']:
            renderprog(0.4, 0.99, "AntiAliasing")
            # Resize to 50% using bi-linear filtering
            img = img.resized(width / 2,
                              height / 2,
                              filter=image.FILTER_BILINEAR)
            # TODO still haven't figured out where components get swapped, but this hack appears to be necessary
            img.data[:, :, :] = img.data[:, :, (2, 1, 0, 3)]
        renderprog.finish()

    if settings['lightmapSSS']:
        progress(0.98, 0.99, "Restoring data")
        human.material = materialBackup

    progress(1, None, 'Rendering complete')

    gui3d.app.getCategory('Rendering').getTaskByName('Viewer').setImage(img)
    mh.changeTask('Rendering', 'Viewer')
    gui3d.app.statusPersist('Rendering complete')
Ejemplo n.º 21
0
def Render(settings):
    progress = Progress.begin()
    
    if not mh.hasRenderToRenderbuffer():
        settings['dimensions'] = (G.windowWidth, G.windowHeight)

    if settings['lightmapSSS']:
        progress(0, 0.05, "Storing data")
        import material
        human = G.app.selectedHuman
        materialBackup = material.Material(human.material)

        progress(0.05, 0.1, "Projecting lightmaps")
        diffuse = imgop.Image(data = human.material.diffuseTexture)
        lmap = projection.mapSceneLighting(
            settings['scene'], border = human.material.sssRScale)
        progress(0.1, 0.4, "Applying medium scattering")
        lmapG = imgop.blurred(lmap, human.material.sssGScale, 13)
        progress(0.4, 0.7, "Applying high scattering")
        lmapR = imgop.blurred(lmap, human.material.sssRScale, 13)
        lmap = imgop.compose([lmapR, lmapG, lmap])
        if not diffuse.isEmpty:
            progress(0.7, 0.8, "Combining textures")
            lmap = imgop.resized(lmap, diffuse.width, diffuse.height, filter=image.FILTER_BILINEAR)
            progress(0.8, 0.9)
            lmap = imgop.multiply(lmap, diffuse)
        lmap.sourcePath = "Internal_Renderer_Lightmap_SSS_Texture"

        progress(0.9, 0.95, "Setting up renderer")
        human.material.diffuseTexture = lmap
        human.configureShading(diffuse = True)
        human.shadeless = True
        progress(0.95, 0.98, None)
    else:
        progress(0, 0.99, None)
        
    if not mh.hasRenderToRenderbuffer():
        # Limited fallback mode, read from screen buffer
        log.message("Fallback render: grab screen")
        img = mh.grabScreen(0, 0, G.windowWidth, G.windowHeight)
        alphaImg = None
    else:
        # Render to framebuffer object
        renderprog = Progress()
        renderprog(0, 0.99 - 0.59 * settings['AA'], "Rendering")
        width, height = settings['dimensions']
        log.message("Rendering at %sx%s", width, height)
        if settings['AA']:
            width = width * 2
            height = height * 2
        img = mh.renderToBuffer(width, height)
        alphaImg = mh.renderAlphaMask(width, height)
        img = imgop.addAlpha(img, imgop.getChannel(alphaImg, 0))

        if settings['AA']:
            renderprog(0.4, 0.99, "AntiAliasing")
            # Resize to 50% using bi-linear filtering
            img = img.resized(width/2, height/2, filter=image.FILTER_BILINEAR)
            # TODO still haven't figured out where components get swapped, but this hack appears to be necessary
            img.data[:,:,:] = img.data[:,:,(2,1,0,3)]
        renderprog.finish()

    if settings['lightmapSSS']:
        progress(0.98, 0.99, "Restoring data")
        human.material = materialBackup

    progress(1, None, 'Rendering complete')

    gui3d.app.getCategory('Rendering').getTaskByName('Viewer').setImage(img)
    mh.changeTask('Rendering', 'Viewer')
    gui3d.app.statusPersist('Rendering complete')
Ejemplo n.º 22
0
def povrayExportMesh2(path, settings):
    """
    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
    ----------

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

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

    progress = Progress.begin()

    # Prepare the output directory.
    progress(0, 0.01, "Preparing Filesystem")
    if not os.path.isdir(path):
        os.makedirs(path)
    log.debug('POV-Ray output folder: %s', path)
    # Cleanup output folder
    for f in os.listdir(path):
        temppath = os.path.join(path, f)
        if os.path.isfile(temppath) and not os.path.splitext(f)[1] == '.png':
            os.remove(temppath)
    # Make empty source output folder
    path = os.path.join(path, 'source/')
    if os.path.isdir(path):
        for f in os.listdir(path):
            os.remove(os.path.join(path, f))
    else:
        os.makedirs(path)
    log.debug('POV-Ray source output folder: %s', path)

    # Open .inc file for writing.
    outputFileDescriptor = open(os.path.join(path, settings['name'] + ".inc"),
                                'w')

    # Write position and dimension constants.
    writeConstants(outputFileDescriptor, settings)

    # Collect and prepare all objects.
    progress(0.01, 0.2, "Analyzing Objects")
    rmeshes = collect.setupMeshes(settings['name'],
                                  gui3d.app.selectedHuman,
                                  hidden=False,
                                  subdivide=settings['subdivide'])

    # Analyze the materials of each richmesh to povray compatible format.
    MAfuncs = {
        'diffusedef':
        lambda T, S:
        'pigment {image_map {%(ft)s "%(fn)s" interpolate 2%(f)s%(t)s}}' % {
            'ft': getImageFType(T.getSaveExt()),
            'fn': T.getSaveName(),
            'f': ' filter all ' + str(S['filter']) if 'filter' in S else "",
            't': ' transmit all ' + str(S['transmit'])
            if 'transmit' in S else ""
        },
        'bumpdef':
        lambda T, S: 'normal {bump_map {%(ft)s "%(fn)s" interpolate 2} %(bi)f}'
        % {
            'ft':
            getImageFType(T.getSaveExt()),
            'fn':
            T.getSaveName(),
            'bi':
            T.Object.rmesh.material.bumpMapIntensity if T.successfulAlternative
            == 0 else T.Object.rmesh.material.displacementMapIntensity
        },
        'alphadef':
        lambda T, S: 'image_map {%(ft)s "%(fn)s" interpolate 2}' % {
            'ft': getImageFType(T.getSaveExt()),
            'fn': T.getSaveName()
        },
        'colordef':
        lambda T, S: 'rgb%(bf)s%(bt)s <#color#%(f)s%(t)s>' % {
            'bf': 'f' if 'filter' in S else "",
            'bt': 't' if 'transmit' in S else "",
            'f': ',' + str(S['filter']) if 'filter' in S else "",
            't': ',' + str(S['transmit']) if 'transmit' in S else ""
        },
        'makecolor':
        lambda s, ct=(1, 1, 1): s.replace('#color#', '%s,%s,%s' % ct),
        'getDiffuseColor':
        lambda T, S: T.Object.rmesh.material.diffuseColor.asTuple(),
        'getAmbience':
        lambda T, S: tuple([(v1 * v2 * S['multiply']
                             if 'multiply' in S else v1 * v2) for (v1, v2)
                            in zip(T.Object.rmesh.material.ambientColor.values,
                                   settings['scene'].environment.ambience)]),
        'specular':
        lambda T, S: str(
            numpy.average(T.Object.rmesh.material.specularColor.values)),
        'roughness':
        lambda T, S: str(1.0 - T.Object.rmesh.material.shininess),
        'diffuseInt':
        lambda T, S: str(T.Object.rmesh.material.diffuseIntensity),
        'pigment':
        lambda s: 'pigment {%s}' % s,
        'lmap':
        lambda RM: projection.mapSceneLighting(settings['scene'], RM.object.
                                               object),
        'blurlev':
        lambda img, mult: (mult * (float(img.width) / 1024)) if img else mult,
        'GBlur':
        lambda RM: RM.material.sssGScale,
        'RBlur':
        lambda RM: RM.material.sssRScale,
        'mapmask':
        lambda RM: projection.mapMask()
    }
    MAfuncs.update(matanalyzer.imgopfuncs)
    materials = matanalyzer.MaterialAnalysis(
        rmeshes,
        map={
            'diffuse':
            (['mat.diffuse'], 'diffusedef',
             ('pigment', ('makecolor', 'colordef', 'getDiffuseColor'))),
            'bump': (['mat.bump', 'mat.displacement'], 'bumpdef', None),
            'alpha': (['mat.transparency',
                       ('getAlpha', 'diffuse')], 'alphadef',
                      ('makecolor', 'colordef', ('param', (1, 1, 1)))),
            'lmap': [('getChannel', 'func.lmap', 1)],
            'bllmap':
            [('blur', 'lmap', ('blurlev', 'lmap', 'func.GBlur'), 13)],
            'bl2lmap':
            [('blur', 'bllmap', ('blurlev', 'lmap', 'func.RBlur'), 13)],
            'sss_bluelmap': [('compose', ('list', 'black', 'black', 'lmap'))],
            'sss_greenlmap':
            [('compose', ('list', 'black', 'bllmap', 'black'))],
            'sss_redlmap': [('compose', ('list', 'bl2lmap', 'black', 'black'))
                            ],
            'sss_alpha': [('blur', ('shrinkMask', 'func.mapmask', 4), 4, 13)],
            'sss_bluebump': ([('getChannel', 'bump', 1)], 'bumpdef', None),
            'sss_greenbump': ([('blur', 'sss_bluebump',
                                ('blurlev', 'sss_bluebump', 'func.GBlur'), 15)
                               ], 'bumpdef', None),
            'sss_redbump': ([('blur', 'sss_greenbump',
                              ('blurlev', 'sss_bluebump', 'func.RBlur'), 15)],
                            'bumpdef', None),
            'hairbump': (['bump'], 'bumpdef', 'alpha.bumpdef'),
            'ambient': ([None], ('makecolor', 'colordef', 'getAmbience')),
            'specular': ([None], 'specular'),
            'roughness': ([None], 'roughness'),
            'diffuseInt': ([None], 'diffuseInt'),
            'black': [('black', 'lmap')]
        },
        functions=MAfuncs)

    # If SSS is enabled, render the lightmaps.
    progress(0.25, 0.6, "Processing SubSurface Scattering")
    povrayProcessSSS(rmeshes, materials, path, settings)

    # Write mesh data for the object.
    progress(0.6, 0.9, "Writing Objects")
    povrayWriteMesh2(outputFileDescriptor, rmeshes)

    progress(0.9, 0.95, "Writing Materials")
    writeLights(settings['scene'], outputFileDescriptor)
    writeMaterials(outputFileDescriptor, rmeshes, materials, settings)
    outputFileDescriptor.close()

    # Write .pov scene file.
    writeScene(os.path.join(path, settings['name'] + ".pov"), rmeshes,
               settings)

    progress(0.95, 0.99, "Writing Textures")
    writeTextures(materials, path)

    progress(1.0, None,
             "Finished. Pov-Ray scene file exported successfully at %s" % path)
Ejemplo n.º 23
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.º 24
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
    config.setupTexFolder(filepath)
    filename = os.path.basename(filepath)
    name = config.goodName(os.path.splitext(filename)[0])

    # TODO this should probably be the only option
    config.zUp = True
    config.feetOnGround = True
    config.scale = 5  # Override scale setting to a sensible default for doom-style engines

    humanBBox = human.meshData.calcBBox()

    objects = human.getObjects(excludeZeroFaceObjs=True)
    meshes = [obj.mesh.clone(config.scale, True) for obj in objects]
    # TODO set good names for meshes

    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(meshes)))

    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(meshes))
    for meshIdx, mesh in enumerate(meshes):
        objprog = Progress()
        objprog(0.0, 0.1, "Writing %s mesh." % mesh.name)

        obj = mesh.object

        # Make sure r_... members are initiated
        mesh.updateIndexBuffer()

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

        f.write('mesh {\n')
        mat = mesh.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")
            rawWeights = human.getVertexWeights()

            # Remap vertex weights to mesh
            if obj.proxy:
                # Determine vertex weights for proxy
                parentWeights = obj.proxy.getVertexWeights(rawWeights)
            else:
                parentWeights = rawWeights
            # Account for vertices that are filtered out
            weights = mesh.getVertexWeights(parentWeights)

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

            # Build a weights list indexed per vertex  # TODO this can be done easier by compiling VertexBoneWeights data
            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.data.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." % mesh.name)
        # Write vertices
        wCount = 0
        for vert in xrange(numVerts):
            if mesh.has_uv:
                u, v = mesh.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." % mesh.name)
        # Write faces
        f.write('\n\tnumtris %d\n' % numFaces)
        fn = 0
        for fv in mesh.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." % mesh.name)
        # Write bone weighting
        bwprog = Progress(len(mesh.r_coord)).HighFrequency(200)
        if human.getSkeleton():
            f.write('\n\tnumweights %d\n' % wCount)
            wCount = 0
            for idx, co in enumerate(mesh.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] *= config.scale
                        #relPos = np.dot(relPos, invbonematrix)
                    else:
                        relPos = co[:3] * config.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(mesh.r_coord):
                # weight [weightIndex] [jointIndex] [weightValue] ( [xPos] [yPos] [zPos] )
                co = co.copy()

                if config.feetOnGround:
                    co += config.offset

                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.º 25
0
def Render(settings):
    progress = Progress.begin()

    if not mh.hasRenderToRenderbuffer():
        settings['dimensions'] = (G.windowWidth, G.windowHeight)

    if settings['lightmapSSS']:
        progress(0, 0.05, "Storing data")
        import material
        human = G.app.selectedHuman
        materialBackup = material.Material(human.material)

        progress(0.05, 0.1, "Projecting lightmaps")
        diffuse = imgop.Image(data=human.material.diffuseTexture)
        lmap = projection.mapSceneLighting(settings['scene'],
                                           border=human.material.sssRScale)
        progress(0.1, 0.4, "Applying medium scattering")
        lmapG = imgop.blurred(lmap, human.material.sssGScale, 13)
        progress(0.4, 0.7, "Applying high scattering")
        lmapR = imgop.blurred(lmap, human.material.sssRScale, 13)
        lmap = imgop.compose([lmapR, lmapG, lmap])
        if not diffuse.isEmpty:
            progress(0.7, 0.8, "Combining textures")
            lmap = imgop.resized(lmap, diffuse.width, diffuse.height)
            progress(0.8, 0.9)
            lmap = imgop.multiply(lmap, diffuse)
        lmap.sourcePath = "Internal_Renderer_Lightmap_SSS_Texture"

        progress(0.9, 0.95, "Setting up renderer")
        human.material.diffuseTexture = lmap
        human.mesh.configureShading(diffuse=True)
        human.mesh.shadeless = True
        progress(0.95, 0.98, None)
    else:
        progress(0, 0.99, None)

    if not mh.hasRenderToRenderbuffer():
        # Limited fallback mode, read from screen buffer
        log.message("Fallback render: grab screen")
        img = mh.grabScreen(0, 0, G.windowWidth, G.windowHeight)
        alphaImg = None
    else:
        # Render to framebuffer object
        renderprog = Progress()
        renderprog(0, 0.99 - 0.59 * settings['AA'], "Rendering")
        width, height = settings['dimensions']
        log.message("Rendering at %sx%s", width, height)
        if settings['AA']:
            width = width * 2
            height = height * 2
        img = mh.renderToBuffer(width, height)
        alphaImg = mh.renderAlphaMask(width, height)
        img = imgop.addAlpha(img, imgop.getChannel(alphaImg, 0))

        if settings['AA']:
            renderprog(0.4, 0.99, "AntiAliasing")
            # Resize to 50% using Qt image class
            qtImg = img.toQImage()
            del img
            # Bilinear filtered resize for anti-aliasing
            scaledImg = qtImg.scaled(
                width / 2,
                height / 2,
                transformMode=gui.QtCore.Qt.SmoothTransformation)
            del qtImg
            img = scaledImg
            #img = image.Image(scaledImg)    # Convert back to MH image
            #del scaledImg
        renderprog.finish()

    if settings['lightmapSSS']:
        progress(0.98, 0.99, "Restoring data")
        human.material = materialBackup

    progress(1, None, 'Rendering complete')

    gui3d.app.getCategory('Rendering').getTaskByName('Viewer').setImage(img)
    mh.changeTask('Rendering', 'Viewer')
    gui3d.app.statusPersist('Rendering complete.')