def loadBvh(self, filepath, convertFromZUp="auto"):
     bvh_file = bvh.load(filepath, convertFromZUp)
     self.autoScaleBVH(bvh_file)  # TODO scaling once is probably not enough, every time the height of the human changes significantly the animation needs to be rescaled
     anim = bvh_file.createAnimationTrack(self.human.getBaseSkeleton())
     _, _, _, license = self.getMetadata(filepath)
     anim.license = license
     return anim
Ejemplo n.º 2
0
 def loadBvh(self, filepath, convertFromZUp="auto"):
     bvh_file = bvh.load(filepath, convertFromZUp)
     self.autoScaleBVH(bvh_file)
     anim = bvh_file.createAnimationTrack(self.human.getBaseSkeleton())
     _, _, _, license = self.getMetadata(filepath)
     anim.license = license
     return anim
Ejemplo n.º 3
0
    def _load_pose_units(self):
        from collections import OrderedDict
        self.base_bvh = bvh.load(
            getpath.getSysDataPath('poseunits/face-poseunits.bvh'),
            allowTranslation="none")
        self.base_anim = self.base_bvh.createAnimationTrack(
            self.human.getBaseSkeleton(), name="Expression-Face-PoseUnits")

        poseunit_json = json.load(open(
            getpath.getSysDataPath('poseunits/face-poseunits.json'),
            'r',
            encoding='utf-8'),
                                  object_pairs_hook=OrderedDict)
        self.poseunit_names = poseunit_json['framemapping']
        log.message('unit pose frame count:%s', len(self.poseunit_names))

        self.modifiers = dict(
            list(zip(self.poseunit_names,
                     len(self.poseunit_names) * [0.0])))
        self.base_poseunit = animation.PoseUnit(
            self.base_anim.name, self.base_anim.data[:self.base_anim.nBones *
                                                     len(self.poseunit_names)],
            self.poseunit_names)

        self._load_gui()
Ejemplo n.º 4
0
    def loadMixPose(self, filename):
        log.debug("Loading special mix pose from %s", filename)
        self.selectedFile = filename
        if not filename:
            # Unload current pose
            self.selectedFile = None
            self.selectedPose = None
            # Remove the special pose from existing pose by restoring the original
            org_pose = self._get_current_unmodified_pose()
            if org_pose is None:
                self.human.setActiveAnimation(None)
            elif self.human.hasAnimation(org_pose.name):
                self.human.setActiveAnimation(org_pose.name)
            else:
                self.human.addAnimation(org_pose)
                self.human.setActiveAnimation(org_pose.name)

            # Remove pose reserved for ... pose library from human
            if self.human.hasAnimation('special-mix-pose'):
                self.human.removeAnimation('special-mix-pose')
            self.human.refreshPose(updateIfInRest=True)
            return

        # Load pose
        #bvh_file = animation.loadPoseFromMhpFile(filename,self.human.getBaseSkeleton()) #bvh.load(filename, convertFromZUp="auto")
        #anim = animation.loadPoseFromMhpFile(filename,self.human.getBaseSkeleton()) #bvh.load(filename, convertFromZUp="auto")
        skel=self.human.getBaseSkeleton()
        bvh_file = bvh.load(filename, convertFromZUp="auto")
        anim = bvh_file.createAnimationTrack(self.human.getBaseSkeleton())
        self.affected_bone_idxs=[]
        with open(filename[0:-4]+".bones") as fp:
            for line in fp:
                self.affected_bone_idxs.append(skel.getBone(line.strip('\n')).index)
        self.applyMixPose(anim)
    def loadFootPose(self, filename):
        log.debug("Loading special foot pose from %s", filename)
        self.selectedFile = filename
        if not filename:
            # Unload current pose
            self.selectedFile = None
            self.selectedPose = None
            # Remove the special pose from existing pose by restoring the original
            org_pose = self._get_current_unmodified_pose()
            if org_pose is None:
                self.human.setActiveAnimation(None)
            elif self.human.hasAnimation(org_pose.name):
                self.human.setActiveAnimation(org_pose.name)
            else:
                self.human.addAnimation(org_pose)
                self.human.setActiveAnimation(org_pose.name)

            # Remove pose reserved for foot pose library from human
            if self.human.hasAnimation('special-foot-pose'):
                self.human.removeAnimation('special-foot-pose')
            self.human.refreshPose(updateIfInRest=True)
            return

        # Load pose
        bvh_file = bvh.load(filename, convertFromZUp="auto")
        anim = bvh_file.createAnimationTrack(self.human.getBaseSkeleton())
        self.applyFootPose(anim)
Ejemplo n.º 6
0
    def _load_pose_units(self):
        from collections import OrderedDict
        self.base_bvh = bvh.load(
            getpath.getSysDataPath('poseunits/face-poseunits.bvh'),
            allowTranslation="none")
        self.base_anim = self.base_bvh.createAnimationTrack(
            self.human.getBaseSkeleton(), name="Expression-Face-PoseUnits")

        poseunit_json = json.load(io.open(
            getpath.getSysDataPath('poseunits/face-poseunits.json'),
            'r',
            encoding='utf-8'),
                                  object_pairs_hook=OrderedDict)
        self.poseunit_names = poseunit_json['framemapping']

        if len(self.poseunit_names) != self.base_bvh.frameCount:
            self.base_anim = None
            raise RuntimeError(
                "Face units BVH has wrong number of frames (%s) while face-poseunits.json defines %s poses, they should be equal."
                % (self.base_bvh.frameCount, len(self.poseunit_names)))
        self.base_anim = animation.PoseUnit(self.base_anim.name,
                                            self.base_anim._data,
                                            self.poseunit_names)
        log.message('unit pose frame count:%s', len(self.poseunit_names))

        # Store indexes of all bones affected by face unit poses, should be all face bones
        self.face_bone_idxs = sorted(
            list(
                set([
                    bIdx for l in self.base_anim.getAffectedBones()
                    for bIdx in l
                ])))
Ejemplo n.º 7
0
 def onClicked(file):
     #if os.path.isdir(path):
     print '[BVHAnimLibrary: onClicked] File value changed:' + file
     self.path.setText(file)
     if os.path.isfile(file):
         self.BVH = bvh.load(file)
         #self.BVH.fromFile(file)
         print '[BVHAnimLibrary: onClicked] Loaded BVH file'
Ejemplo n.º 8
0
 def onClicked(file):
     # if os.path.isdir(path):
     print "[BVHAnimLibrary: onClicked] File value changed:" + file
     self.path.setText(file)
     if os.path.isfile(file):
         self.BVH = bvh.load(file)
         # self.BVH.fromFile(file)
         print "[BVHAnimLibrary: onClicked] Loaded BVH file"
Ejemplo n.º 9
0
def loadAnimationTrack(anim):
    """
    Load animation from a BVH file specified by anim.
    """
    if "z_is_up" in anim.options:
        swapYZ = True
    else:
        swapYZ = False

    human = gui3d.app.selectedHuman

    log.debug("Loading BVH %s", anim.getPath())

    # Load BVH data
    bvhRig = bvh.load(anim.getPath(), swapYZ)
    if anim.collection.scale != 1.0:
        # Scale rig
        bvhRig.scale(scale)
        # Scale is only useful when using the joint locations of the BVH rig
        # or when drawing the BVH rig.

    if human.getSkeleton().name == anim.collection.rig:
        # Skeleton and joint rig in BVH match, do a straight mapping of the
        # motion:

        # Load animation data from BVH file and add it to AnimatedMesh
        # This is a list that references a joint name in the BVH for each
        # bone in the skeleton (breadth-first order):
        jointToBoneMap = [bone.name for bone in human.getSkeleton().getBones()]
        animTrack = bvhRig.createAnimationTrack(jointToBoneMap,
                                                anim.getAnimationTrackName())
        gui3d.app.statusPersist("")
    else:
        # Skeleton and joint rig in BVH are not the same, retarget/remap
        # the motion data:
        gui3d.app.statusPersist(
            "Currently, animation are only working with soft1 rig, please choose the soft1 rig from the skeleton chooser."
        )
        return None

        if not os.path.isfile(
                "tools/blender26x/mh_mocap_tool/target_rigs/%s.trg" %
                human.getSkeleton().name):
            gui3d.app.statusPersist(
                "Cannot apply motion on the selected skeleton %s because there is no target mapping file for it.",
                human.getSkeleton().name)
            return None

        jointToBoneMap = skeleton.loadJointsMapping(human.getSkeleton().name,
                                                    human.getSkeleton())
        animTrack = bvhRig.createAnimationTrack(jointToBoneMap,
                                                anim.getAnimationTrackName())

    log.debug("Created animation track for %s rig.", human.getSkeleton().name)
    log.debug("Frames: %s", animTrack.nFrames)
    log.debug("Playtime: %s", animTrack.getPlaytime())

    return animTrack
 def loadBvh(self, filepath, convertFromZUp="auto"):
     bvh_file = bvh.load(filepath, convertFromZUp)
     self.autoScaleBVH(
         bvh_file
     )  # TODO scaling once is probably not enough, every time the height of the human changes significantly the animation needs to be rescaled
     anim = bvh_file.createAnimationTrack(self.human.getBaseSkeleton())
     _, _, _, license = self.getMetadata(filepath)
     anim.license = license
     return anim
Ejemplo n.º 11
0
def get_blank_pose():
    human = gui3d.app.selectedHuman
    base_bvh = bvh.load(getpath.getSysDataPath('poseunits/face-poseunits.bvh'), allowTranslation="none")
    base_anim = base_bvh.createAnimationTrack(human.getBaseSkeleton(), name="Expression-Face-PoseUnits")

    poseunit_json = json.load(open(getpath.getSysDataPath('poseunits/face-poseunits.json'),'rb'), object_pairs_hook=OrderedDict)
    # the names of the changeable facial expression features
    poseunit_names = poseunit_json['framemapping']
    modifiers = dict(zip(poseunit_names, len(poseunit_names)*[0.0]))
    base_poseunit = animation.PoseUnit(base_anim.name, base_anim.data[:base_anim.nBones*len(poseunit_names)], poseunit_names)
    return modifiers, base_poseunit
Ejemplo n.º 12
0
    def setExpressionFromFile(self, mhposeFile):
        """Set the expression from a mhpose file"""

        if mhposeFile is None:
            # clear expression

            original_pose = self.getPoseAsAnimation()
            if original_pose and hasattr(original_pose, 'pose_backref'):
                original_pose = original_pose.pose_backref
    
            if original_pose is None:
                self.human.setActiveAnimation(None)
            else:
                if self.human.hasAnimation(original_pose.name):
                    self.human.setActiveAnimation(original_pose.name)
                else:
                    self.human.addAnimation(original_pose)
                    self.human.setActiveAnimation(orgiginal_pose.name)
    
            if self.human.hasAnimation('expr-lib-pose'):
                self.human.removeAnimation('expr-lib-pose')
        else:
            # Assign expression
            
            base_bvh = bvh.load(getpath.getSysDataPath('poseunits/face-poseunits.bvh'), allowTranslation="none")
            base_anim = base_bvh.createAnimationTrack(self.human.getBaseSkeleton(), name="Expression-Face-PoseUnits")

            poseunit_json = json.load(open(getpath.getSysDataPath('poseunits/face-poseunits.json'), 'r', encoding='utf-8'), object_pairs_hook=OrderedDict)
            poseunit_names = poseunit_json['framemapping']

            base_anim = animation.PoseUnit(base_anim.name, base_anim._data, poseunit_names)

            face_bone_idxs = sorted(list(set([bIdx for l in base_anim.getAffectedBones() for bIdx in l])))

            new_pose = animation.poseFromUnitPose('expr-lib-pose', mhposeFile, base_anim)

            current_pose = self.getPoseAsAnimation()

            if current_pose is None:
                current_pose = new_pose
                current_pose.pose_backref = None
            else:
                if hasattr(current_pose,'pose_backref') and not current_pose.pose_backref is None:
                    current_pose = current_pose.pose_backref
                org_pose = current_pose
                current_pose = animation.mixPoses(org_pose, new_pose, face_bone_idxs)

            current_pose.name = 'expr-lib-pose'
            self.human.addAnimation(current_pose)
            self.human.setActiveAnimation(current_pose.name)
            self.human.setPosed(True)
            self.human.refreshPose()
    def _load_pose_units(self):
        from collections import OrderedDict
        self.base_bvh = bvh.load(getpath.getSysDataPath('poseunits/face-poseunits.bvh'), allowTranslation="none")
        self.base_anim = self.base_bvh.createAnimationTrack(self.human.getBaseSkeleton(), name="Expression-Face-PoseUnits")

        poseunit_json = json.load(open(getpath.getSysDataPath('poseunits/face-poseunits.json'),'rb'), object_pairs_hook=OrderedDict)
        self.poseunit_names = poseunit_json['framemapping']
        log.message('unit pose frame count:%s', len(self.poseunit_names))

        self.modifiers = dict(zip(self.poseunit_names, len(self.poseunit_names)*[0.0]))
        self.base_poseunit = animation.PoseUnit(self.base_anim.name, self.base_anim.data[:self.base_anim.nBones*len(self.poseunit_names)], self.poseunit_names)

        self._load_gui()
Ejemplo n.º 14
0
    def loadAnimation(self, filename):
        global SPARSIFY

        log.message("Loading BVH animation %s", filename)
        animName = unicode(os.path.splitext(os.path.basename(filename))[0])
        self.stopPlayback()
        if not self.animated.hasAnimation(animName):
            # TODO cache bvh file (and mappings)
            bvhRig = bvh.load(filename)
            # TODO scale bvh by comparing upper leg length
            bvhRig.scale(0.7)
            bvhRig.filename = filename

            # TODO cache mapping
            #jointToBoneMap = skeleton.loadJointsMapping("soft1", self.skel)
            retargetMapping = skeleton.getRetargetMapping(
                'mb', 'soft1', self.skel)
            #retargetMapping = skeleton.getRetargetMappingFromBVH(bvhRig, 'soft1', self.skel)
            # TODO guess format of source rig

            animTrack = bvhRig.createAnimationTrack(retargetMapping, animName)
            if SPARSIFY:
                if animTrack.frameRate > 30:
                    animTrack.sparsify(30)

            self.animated.addAnimation(animTrack)

            #self.__bvhRigCache['mb']  # TODO cache rig for all BVH rig types, for now we assume all BVHs are mb format
        else:
            animTrack = self.animated.getAnimation(animName)

        if not self.bvhAnimated or not self.bvhAnimated.hasAnimation(animName):
            # Draw BVH rig and/or add animation
            self.loadBVHRig(bvhRig)

        self.animated.setActiveAnimation(animName)
        self.anim = animTrack
        self.anim.interpolationType = 0
        self.createPlaybackControl()
        self.animated.setAnimateInPlace(self.animateInPlaceTggl.selected)
        self.animated.setToFrame(0)
        self.setShowRig(self.showMHXRigTggl.selected)

        self.bvhAnimated.setActiveAnimation(animName)
        self.bvhAnimated.setAnimateInPlace(self.animateInPlaceTggl.selected)
        self.bvhAnimated.setToFrame(0)
        self.setShowBVHRig(self.showBVHRigTggl.selected)

        self.__setSelectedAnimation(filename)
        self.startPlayback()
Ejemplo n.º 15
0
 def loadBvh(self, filepath, convertFromZUp="auto"):
     bvh_file = bvh.load(filepath, convertFromZUp)
     anim = bvh_file.createAnimationTrack(self.human.getBaseSkeleton())
     if "root" in bvh_file.joints:
         posedata = anim.getAtFramePos(0, noBake=True)
         root_bone_idx = 0
         self.bvh_root_translation = posedata[root_bone_idx, :3, 3].copy()
     else:
         self.bvh_root_translation = np.asarray(3 * [0.0], dtype=np.float32)
     self.bvh_bone_length = self.calculateBvhBoneLength(bvh_file)
     self.autoScaleAnim(anim)
     _, _, _, license = self.getMetadata(filepath)
     anim.license = license
     return anim
 def loadBvh(self, filepath, convertFromZUp="auto"):
     bvh_file = bvh.load(filepath, convertFromZUp)
     anim = bvh_file.createAnimationTrack(self.human.getBaseSkeleton())
     if "root" in bvh_file.joints:
         posedata = anim.getAtFramePos(0, noBake=True)
         root_bone_idx = 0
         self.bvh_root_translation = posedata[root_bone_idx, :3, 3].copy()
     else:
         self.bvh_root_translation = np.asarray(3*[0.0], dtype=np.float32)
     self.bvh_bone_length = self.calculateBvhBoneLength(bvh_file)
     self.autoScaleAnim(anim)
     _, _, _, license = self.getMetadata(filepath)
     anim.license = license
     return anim
def loadAnimationTrack(anim):
    """
    Load animation from a BVH file specified by anim.
    """
    if "z_is_up" in anim.options:
        swapYZ = True
    else:
        swapYZ = False

    human = gui3d.app.selectedHuman

    log.debug("Loading BVH %s", anim.getPath())

    # Load BVH data
    bvhRig = bvh.load(anim.getPath(), swapYZ)
    if anim.collection.scale != 1.0:
        # Scale rig
        bvhRig.scale(scale)
        # Scale is only useful when using the joint locations of the BVH rig
        # or when drawing the BVH rig.

    if human.getSkeleton().name == anim.collection.rig:
        # Skeleton and joint rig in BVH match, do a straight mapping of the
        # motion:

        # Load animation data from BVH file and add it to AnimatedMesh
        # This is a list that references a joint name in the BVH for each 
        # bone in the skeleton (breadth-first order):
        jointToBoneMap = [bone.name for bone in human.getSkeleton().getBones()]
        animTrack = bvhRig.createAnimationTrack(jointToBoneMap, anim.getAnimationTrackName())
        gui3d.app.statusPersist("")
    else:
        # Skeleton and joint rig in BVH are not the same, retarget/remap
        # the motion data:
        gui3d.app.statusPersist("Currently, animation are only working with soft1 rig, please choose the soft1 rig from the skeleton chooser.")
        return None

        if not os.path.isfile("tools/blender26x/mh_mocap_tool/target_rigs/%s.trg" % human.getSkeleton().name):
            gui3d.app.statusPersist("Cannot apply motion on the selected skeleton %s because there is no target mapping file for it.", human.getSkeleton().name)
            return None

        jointToBoneMap = skeleton.loadJointsMapping(human.getSkeleton().name, human.getSkeleton())
        animTrack = bvhRig.createAnimationTrack(jointToBoneMap, anim.getAnimationTrackName())

    log.debug("Created animation track for %s rig.", human.getSkeleton().name)
    log.debug("Frames: %s", animTrack.nFrames)
    log.debug("Playtime: %s", animTrack.getPlaytime())

    return animTrack
Ejemplo n.º 18
0
    def loadAnimation(self, filename):
        global SPARSIFY

        log.message("Loading BVH animation %s", filename)
        animName = unicode(os.path.splitext(os.path.basename(filename))[0])
        self.stopPlayback()
        if not self.animated.hasAnimation(animName):
            # TODO cache bvh file (and mappings)
            bvhRig = bvh.load(filename)
            # TODO scale bvh by comparing upper leg length
            bvhRig.scale(0.7)
            bvhRig.filename = filename

            # TODO cache mapping
            #jointToBoneMap = skeleton.loadJointsMapping("soft1", self.skel)
            retargetMapping = skeleton.getRetargetMapping('mb', 'soft1', self.skel)
            #retargetMapping = skeleton.getRetargetMappingFromBVH(bvhRig, 'soft1', self.skel)
            # TODO guess format of source rig

            animTrack = bvhRig.createAnimationTrack(retargetMapping, animName)
            if SPARSIFY:
                if animTrack.frameRate > 30:
                    animTrack.sparsify(30)

            self.animated.addAnimation(animTrack)

            #self.__bvhRigCache['mb']  # TODO cache rig for all BVH rig types, for now we assume all BVHs are mb format
        else:
            animTrack = self.animated.getAnimation(animName)

        if not self.bvhAnimated or not self.bvhAnimated.hasAnimation(animName):
            # Draw BVH rig and/or add animation
            self.loadBVHRig(bvhRig)

        self.animated.setActiveAnimation(animName)
        self.anim = animTrack
        self.anim.interpolationType = 0
        self.createPlaybackControl()
        self.animated.setAnimateInPlace(self.animateInPlaceTggl.selected)
        self.animated.setToFrame(0)
        self.setShowRig(self.showMHXRigTggl.selected)

        self.bvhAnimated.setActiveAnimation(animName)
        self.bvhAnimated.setAnimateInPlace(self.animateInPlaceTggl.selected)
        self.bvhAnimated.setToFrame(0)
        self.setShowBVHRig(self.showBVHRigTggl.selected)

        self.__setSelectedAnimation(filename)
        self.startPlayback()
Ejemplo n.º 19
0
    def __init__(self, category):
        gui3d.TaskView.__init__(self, category, 'Expressions')

        self.human = gui3d.app.selectedHuman

        # TODO defer loading to first onShow()
        bvhfile = bvh.load(getpath.getSysDataPath('poseunits/face-poseunits.bvh'), allowTranslation="none")
        self.base_bvh = bvhfile

        from collections import OrderedDict
        poseunit_json = json.load(open(getpath.getSysDataPath('poseunits/face-poseunits.json'),'rb'), object_pairs_hook=OrderedDict)
        self.poseunit_names = poseunit_json['framemapping']

        self.sliders = []
        self.modifiers = dict(zip(self.poseunit_names, len(self.poseunit_names)*[0.0]))
    def _load_pose_units(self):
        from collections import OrderedDict
        self.base_bvh = bvh.load(getpath.getSysDataPath('poseunits/face-poseunits.bvh'), allowTranslation="none")
        self.base_anim = self.base_bvh.createAnimationTrack(self.human.getBaseSkeleton(), name="Expression-Face-PoseUnits")

        poseunit_json = json.load(open(getpath.getSysDataPath('poseunits/face-poseunits.json'),'rb'), object_pairs_hook=OrderedDict)
        self.poseunit_names = poseunit_json['framemapping']

        if len(self.poseunit_names) != self.base_bvh.frameCount:
            self.base_anim = None
            raise RuntimeError("Face units BVH has wrong number of frames (%s) while face-poseunits.json defines %s poses, they should be equal." % (self.base_bvh.frameCount, len(self.poseunit_names)))
        self.base_anim = animation.PoseUnit(self.base_anim.name, self.base_anim._data, self.poseunit_names)
        log.message('unit pose frame count:%s', len(self.poseunit_names))

        # Store indexes of all bones affected by face unit poses, should be all face bones
        self.face_bone_idxs = sorted(list(set([bIdx for l in self.base_anim.getAffectedBones() for bIdx in l])))
Ejemplo n.º 21
0
def setExpression(expression):
    if expression == "None":
        modifiers, _ = get_blank_pose()
        return modifiers
    with open(expression, 'r') as f:
        human = G.app.objects[0]
        base_bvh = bvh.load(
            getpath.getSysDataPath('poseunits/face-poseunits.bvh'),
            allowTranslation="none")
        base_anim = base_bvh.createAnimationTrack(
            human.getBaseSkeleton(), name="Expression-Face-PoseUnits")

        poseunit_json = json.load(open(
            getpath.getSysDataPath('poseunits/face-poseunits.json'), 'rb'),
                                  object_pairs_hook=OrderedDict)
        # the names of the changeable facial expression features
        poseunit_names = poseunit_json['framemapping']
        modifiers = dict(zip(poseunit_names, len(poseunit_names) * [0.0]))
        base_poseunit = animation.PoseUnit(
            base_anim.name,
            base_anim.data[:base_anim.nBones * len(poseunit_names)],
            poseunit_names)

        pose_modifiers = json.load(f,
                                   object_pairs_hook=OrderedDict)['unit_poses']

        for key in modifiers:
            if key in pose_modifiers:
                modifiers[key] = pose_modifiers[key]

        # see which values are different so only those are updated
        posenames = []
        posevalues = []
        for pname, pval in modifiers.items():
            #if pval != 0:
            posenames.append(pname)
            posevalues.append(pval)
        if len(posenames) > 0:
            panim = base_poseunit.getBlendedPose(posenames, posevalues)
            panim.disableBaking = False

            human.addAnimation(panim)
            human.setActiveAnimation(panim.name)
            human.refreshPose()
        return modifiers
Ejemplo n.º 22
0
 def loadBvh(self, filepath, convertFromZUp="auto"):
     bvh_file = bvh.load(filepath, convertFromZUp)
     if COMPARE_BONE not in bvh_file.joints:
         msg = 'The pose file cannot be used. It uses a rig different from MakeHuman\'s defualt rig'
         G.app.prompt('Error', msg, 'OK')
         log.error('Pose file %s does not use the default rig.' % filepath)
         return None
     anim = bvh_file.createAnimationTrack(self.human.getBaseSkeleton())
     if "root" in bvh_file.joints:
         posedata = anim.getAtFramePos(0, noBake=True)
         root_bone_idx = 0
         self.bvh_root_translation = posedata[root_bone_idx, :3, 3].copy()
     else:
         self.bvh_root_translation = np.asarray(3*[0.0], dtype=np.float32)
     self.bvh_bone_length = self.calculateBvhBoneLength(bvh_file)
     self.autoScaleAnim(anim)
     _, _, _, license = self.getMetadata(filepath)
     anim.license = license
     return anim
Ejemplo n.º 23
0
    def __init__(self, category):
        gui3d.TaskView.__init__(self, category, 'Expressions')

        self.human = gui3d.app.selectedHuman

        # TODO defer loading to first onShow()
        bvhfile = bvh.load(
            getpath.getSysDataPath('poseunits/face-poseunits.bvh'),
            allowTranslation="none")
        self.base_bvh = bvhfile

        from collections import OrderedDict
        poseunit_json = json.load(open(
            getpath.getSysDataPath('poseunits/face-poseunits.json'), 'rb'),
                                  object_pairs_hook=OrderedDict)
        self.poseunit_names = poseunit_json['framemapping']

        self.sliders = []
        self.modifiers = dict(
            zip(self.poseunit_names,
                len(self.poseunit_names) * [0.0]))
Ejemplo n.º 24
0
def loadAnimationTrack(anim):
    """
    Load animation from a BVH file specified by anim.
    """
    global _jointMappingCache

    if "z_is_up" in anim.options:
        swapYZ = True
    else:
        swapYZ = False

    human = gui3d.app.selectedHuman

    log.debug("Loading BVH %s", anim.getPath())

    # Load BVH data
    bvhRig = bvh.load(anim.getPath(), swapYZ)
    if anim.collection.scale != 1.0:
        # Scale rig
        bvhRig.scale(anim.collection.scale)
        # Scale is only useful when using the joint locations of the BVH rig
        # or when drawing the BVH rig.

    if human.getSkeleton().name == anim.collection.rig:
        # Skeleton and joint rig in BVH match, do a straight mapping of the
        # motion:

        # Load animation data from BVH file and add it to AnimatedMesh
        # This is a list that references a joint name in the BVH for each
        # bone in the skeleton (breadth-first order):
        jointToBoneMap = [bone.name for bone in human.getSkeleton().getBones()]
        animTrack = bvhRig.createAnimationTrack(jointToBoneMap,
                                                anim.getAnimationTrackName())
        gui3d.app.statusPersist("")
    else:
        # Skeleton and joint rig in BVH are not the same, retarget/remap
        # the motion data:
        if not os.path.isfile(
                mh.getSysPath(
                    "tools/blender26x/mh_mocap_tool/target_rigs/%s.trg") %
                human.getSkeleton().name):
            gui3d.app.statusPersist(
                "Cannot apply motion on the selected skeleton %s because there is no target mapping file for it.",
                human.getSkeleton().name)
            return None

        # Load source skeleton of animation for remapping
        cacheName = anim.collection.rig + "_" + human.getSkeleton().name
        if cacheName in _jointMappingCache:
            # Load from cache
            jointToBoneMap = _jointMappingCache[cacheName]
        else:
            # Create and cache mapping
            srcSkel, _ = skeleton.loadRig(
                os.path.join(mh.getSysDataPath('rigs'),
                             '%s.rig' % anim.collection.rig), human.meshData)
            tgtSkel = human.getSkeleton()
            # Load mapping from reference rig to target rig
            # TODO this only works if anim.collection.rig == soft1! We cannot do reverse target mappings
            jointToBoneMap = skeleton.getRetargetMapping(
                None,
                human.getSkeleton().name, human.getSkeleton())
            # We dont use the compensation angles from the retarget map, instead we calculate the difference between reference and target rig ourselves
            excludeFromCompensation = ["Root", "Spine1", "Spine2", "Spine3"]
            jointToBoneMap = skeleton.getRestPoseCompensation(
                srcSkel, tgtSkel, jointToBoneMap, excludeFromCompensation)
            _jointMappingCache[cacheName] = jointToBoneMap

        animTrack = bvhRig.createAnimationTrack(jointToBoneMap,
                                                anim.getAnimationTrackName())
        gui3d.app.statusPersist("")

    log.debug("Created animation track for %s rig.", human.getSkeleton().name)
    log.debug("Frames: %s", animTrack.nFrames)
    log.debug("Playtime: %s", animTrack.getPlaytime())

    return animTrack
Ejemplo n.º 25
0
def exportCollada(filepath, config):
    progress = Progress()

    time1 = time.perf_counter()
    human = config.human
    config.setupTexFolder(filepath)
    filename = os.path.basename(filepath)
    name = config.goodName(os.path.splitext(filename)[0])

    progress(0, 0.5, "Preparing")

    objects = human.getObjects(excludeZeroFaceObjs=not config.hiddenGeom)
    # Clone meshes with desired scale and hidden faces/vertices filtered out
    meshes = [
        obj.mesh.clone(config.scale, filterMaskedVerts=not config.hiddenGeom)
        for obj in objects
    ]

    if config.hiddenGeom:
        import numpy as np
        # Disable the face masking on copies of the input meshes
        for m in meshes:
            # Disable the face masking on the mesh
            face_mask = np.ones(m.face_mask.shape, dtype=bool)
            m.changeFaceMask(face_mask)
            m.calcNormals()
            m.updateIndexBuffer()

    # Scale skeleton
    skel = human.getSkeleton()
    if skel:
        if config.scale != 1:
            skel = skel.scaled(config.scale)

    # TODO a shared method for properly naming meshes would be a good idea
    for mesh in meshes:
        if mesh.object.proxy:
            mesh.name = mesh.object.proxy.name
        mesh.name = os.path.splitext(mesh.name)[0]
        mesh.name = name + '-' + config.goodName(mesh.name)

    try:
        progress(0.5, 0.55, "Exporting %s", filepath)

        try:
            fp = io.open(filepath, 'w', encoding="utf-8")
            log.message("Writing Collada file %s" % filepath)
        except:
            fp = None
            log.error("Unable to open file for writing %s" % filepath)

        date = time.strftime("%Y-%m-%dT%H:%M:%S+00:00", time.gmtime())
        # TODO revise to make this enum-like
        if config.yUpFaceZ or config.yUpFaceX:
            upvector = "Y_UP"
        else:
            upvector = "Z_UP"
        fp.write(
            '<?xml version="1.0" encoding="utf-8"?>\n' +
            '<COLLADA version="1.4.1" xmlns="http://www.collada.org/2005/11/COLLADASchema">\n'
            + '  <asset>\n' + '    <contributor>\n' +
            '      <author>www.makehumancommunity.org</author>\n' +
            '    </contributor>\n' + '    <created>%s</created>\n' % date +
            '    <modified>%s</modified>\n' % date +
            '    <unit meter="%.4f" name="%s"/>\n' %
            (0.1 / config.scale, config.unit) +
            '    <up_axis>%s</up_axis>\n' % upvector + '  </asset>\n')

        progress(0.55, 0.6, "Exporting images")
        dae_materials.writeLibraryImages(fp, objects, config)

        progress(0.6, 0.65, "Exporting effects")
        dae_materials.writeLibraryEffects(fp, objects, config)

        progress(0.65, 0.7, "Exporting materials")
        dae_materials.writeLibraryMaterials(fp, objects, config)

        progress(0.7, 0.75, "Exporting controllers")
        dae_controller.writeLibraryControllers(fp, human, meshes, skel, config)

        progress(0.75, 0.8, "Exporting animations")
        #animations = [human.getAnimation(name) for name in human.getAnimations()]  # TODO distinguish poses from animations
        if skel and config.facePoseUnits:
            bvhfile = bvh.load(
                getpath.getSysDataPath('poseunits/face-poseunits.bvh'),
                allowTranslation="none")
            # TODO compensate for rest pose
            faceunit_anim = bvhfile.createAnimationTrack(
                skel, name="Expression-Face-PoseUnits")
            animations = [
                human.getAnimation(name) for name in human.getAnimations()
            ] + [faceunit_anim]
            dae_animation.writeLibraryAnimations(fp, human, skel, animations,
                                                 config)

        progress(0.75, 0.9, "Exporting geometry")
        dae_geometry.writeLibraryGeometry(fp, meshes, config)

        progress(0.9, 0.99, "Exporting scene")
        dae_node.writeLibraryVisualScenes(fp, meshes, skel, config, name)

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

        progress(1, None, "Export finished.")
        time2 = time.perf_counter()
        log.message("Wrote Collada file in %g s: %s", time2 - time1, filepath)

    finally:
        if fp:
            fp.close()
Ejemplo n.º 26
0
def loadAnimationTrack(anim):
    """
    Load animation from a BVH file specified by anim.
    """
    global _jointMappingCache

    if "z_is_up" in anim.options:
        swapYZ = True
    else:
        swapYZ = False

    human = gui3d.app.selectedHuman

    log.debug("Loading BVH %s", anim.getPath())

    # Load BVH data
    bvhRig = bvh.load(anim.getPath(), swapYZ)
    if anim.collection.scale != 1.0:
        # Scale rig
        bvhRig.scale(scale)
        # Scale is only useful when using the joint locations of the BVH rig
        # or when drawing the BVH rig.

    if human.getSkeleton().name == anim.collection.rig:
        # Skeleton and joint rig in BVH match, do a straight mapping of the
        # motion:

        # Load animation data from BVH file and add it to AnimatedMesh
        # This is a list that references a joint name in the BVH for each
        # bone in the skeleton (breadth-first order):
        jointToBoneMap = [bone.name for bone in human.getSkeleton().getBones()]
        animTrack = bvhRig.createAnimationTrack(jointToBoneMap, anim.getAnimationTrackName())
        gui3d.app.statusPersist("")
    else:
        # Skeleton and joint rig in BVH are not the same, retarget/remap
        # the motion data:
        if not os.path.isfile(mh.getSysPath("tools/blender26x/mh_mocap_tool/target_rigs/%s.trg") % human.getSkeleton().name):
            gui3d.app.statusPersist("Cannot apply motion on the selected skeleton %s because there is no target mapping file for it.", human.getSkeleton().name)
            return None

        # Load source skeleton of animation for remapping
        cacheName = anim.collection.rig + "_" + human.getSkeleton().name
        if cacheName in _jointMappingCache:
            # Load from cache
            jointToBoneMap = _jointMappingCache[cacheName]
        else:
            # Create and cache mapping
            srcSkel, _ = skeleton.loadRig(os.path.join(mh.getSysDataPath('rigs'), '%s.rig' % anim.collection.rig), human.meshData)
            tgtSkel = human.getSkeleton()
            # Load mapping from reference rig to target rig
            # TODO this only works if anim.collection.rig == soft1! We cannot do reverse target mappings
            jointToBoneMap = skeleton.getRetargetMapping(None, human.getSkeleton().name, human.getSkeleton())
            # We dont use the compensation angles from the retarget map, instead we calculate the difference between reference and target rig ourselves
            excludeFromCompensation = ["Root", "Spine1", "Spine2", "Spine3"]
            jointToBoneMap = skeleton.getRestPoseCompensation(srcSkel, tgtSkel, jointToBoneMap, excludeFromCompensation)
            _jointMappingCache[cacheName] = jointToBoneMap

        animTrack = bvhRig.createAnimationTrack(jointToBoneMap, anim.getAnimationTrackName())
        gui3d.app.statusPersist("")

    log.debug("Created animation track for %s rig.", human.getSkeleton().name)
    log.debug("Frames: %s", animTrack.nFrames)
    log.debug("Playtime: %s", animTrack.getPlaytime())

    return animTrack
Ejemplo n.º 27
0
 def loadBvh(self, filepath, convertFromZUp="auto"):
     bvh_file = bvh.load(filepath, convertFromZUp)
     self.autoScaleBVH(bvh_file)
     return bvh_file.createAnimationTrack(self.human.getSkeleton())
Ejemplo n.º 28
0
 def loadBvh(self, filepath, convertFromZUp="auto"):
     bvh_file = bvh.load(filepath, convertFromZUp)
     self.autoScaleBVH(bvh_file)
     return bvh_file.createAnimationTrack(self.human.getSkeleton())
Ejemplo n.º 29
0
def exportCollada(filepath, config):
    progress = Progress()

    time1 = time.clock()
    human = config.human
    config.setupTexFolder(filepath)
    filename = os.path.basename(filepath)
    name = config.goodName(os.path.splitext(filename)[0])

    progress(0, 0.5, "Preparing")

    objects = human.getObjects(excludeZeroFaceObjs=True)
    # Clone meshes with desired scale and hidden faces/vertices filtered out
    meshes = [obj.mesh.clone(config.scale, True) for obj in objects]

    # Scale skeleton
    skel = human.getSkeleton()
    if skel:
        if config.scale != 1:
            skel = skel.scaled(config.scale)
        if not skel.isInRestPose():
            # Export skeleton with the current pose as rest pose
            skel = skel.createFromPose()

    # TODO a shared method for properly naming meshes would be a good idea
    for mesh in meshes:
        if mesh.object.proxy:
            mesh.name = mesh.object.proxy.name
        mesh.name = os.path.splitext(mesh.name)[0]
        mesh.name = name + '-' + config.goodName(mesh.name)

    try:
        progress(0.5, 0.55, "Exporting %s", filepath)

        try:
            fp = codecs.open(filepath, 'w', encoding="utf-8")
            log.message("Writing Collada file %s" % filepath)
        except:
            fp = None
            log.error("Unable to open file for writing %s" % filepath)

        date = time.strftime(u"%a, %d %b %Y %H:%M:%S +0000".encode('utf-8'), time.localtime()).decode('utf-8')
        # TODO revise to make this enum-like
        if config.yUpFaceZ or config.yUpFaceX:
            upvector = "Y_UP"
        else:
            upvector = "Z_UP"
        fp.write('<?xml version="1.0" encoding="utf-8"?>\n' +
            '<COLLADA version="1.4.0" xmlns="http://www.collada.org/2005/11/COLLADASchema">\n' +
            '  <asset>\n' +
            '    <contributor>\n' +
            '      <author>www.makehuman.org</author>\n' +
            '    </contributor>\n' +
            '    <created>%s</created>\n' % date +
            '    <modified>%s</modified>\n' % date +
            '    <unit meter="%.4f" name="%s"/>\n' % (0.1/config.scale, config.unit) +
            '    <up_axis>%s</up_axis>\n' % upvector +
            '  </asset>\n')

        progress(0.55, 0.6, "Exporting images")
        dae_materials.writeLibraryImages(fp, objects, config)

        progress(0.6, 0.65, "Exporting effects")
        dae_materials.writeLibraryEffects(fp, objects, config)

        progress(0.65, 0.7, "Exporting materials")
        dae_materials.writeLibraryMaterials(fp, objects, config)

        progress(0.7, 0.75, "Exporting controllers")
        dae_controller.writeLibraryControllers(fp, human, meshes, skel, config)

        progress(0.75, 0.8, "Exporting animations")
        #animations = [human.getAnimation(name) for name in human.getAnimations()]  # TODO distinguish poses from animations
        if skel and config.facePoseUnits:
            bvhfile = bvh.load(getpath.getSysDataPath('poseunits/face-poseunits.bvh'), allowTranslation="none")
            # TODO compensate for rest pose
            faceunit_anim = bvhfile.createAnimationTrack(skel, name="Expression-Face-PoseUnits")
            animations = [faceunit_anim]
            dae_animation.writeLibraryAnimations(fp, human, skel, animations, config)

        progress(0.75, 0.9, "Exporting geometry")
        dae_geometry.writeLibraryGeometry(fp, meshes, config)

        progress(0.9, 0.99, "Exporting scene")
        dae_node.writeLibraryVisualScenes(fp, meshes, skel, config, name)

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

        progress(1, None, "Export finished.")
        time2 = time.clock()
        log.message("Wrote Collada file in %g s: %s", time2-time1, filepath)

    finally:
        if fp:
            fp.close()