def createAnimationTrack(self, jointsOrder=None, name="BVHMotion"): """ Create an animation track from the motion stored in this BHV file. """ if jointsOrder == None: jointsData = [ joint.matrixPoses for joint in self.getJoints() if not joint.isEndConnector() ] # We leave out end effectors as they should not have animation data else: nFrames = self.frameCount import re # Remove the tail from duplicate bone names for idx, jName in enumerate(jointsOrder): # Joint mappings can contain a rotation compensation if isinstance(jName, tuple): jName, _ = jName if not jName: continue r = re.search("(.*)_\d+$", jName) if r: jointsOrder[idx] = r.group(1) jointsData = [] for jointName in jointsOrder: if isinstance(jointName, tuple): jointName, angle = jointName else: angle = 0.0 if jointName: poseMats = self.getJointByCanonicalName( jointName).matrixPoses.copy() if isinstance(angle, float): if angle != 0.0: # Rotate around global Z axis rot = tm.rotation_matrix(-angle * D, [0, 0, 1]) # Roll around global Y axis (this is a limitation) roll = tm.rotation_matrix(angle * D, [0, 1, 0]) for i in xrange(nFrames): # TODO make into numpy loop poseMats[i] = np.dot(poseMats[i], rot) poseMats[i] = np.dot(poseMats[i], roll) else: # Compensation (angle) is a transformation matrix # Compensate animation frames for i in xrange(nFrames): # TODO make into numpy loop poseMats[i] = np.mat(poseMats[i]) * np.mat(angle) #poseMats[i] = np.mat(angle) # Test compensated rest pose jointsData.append(poseMats) else: jointsData.append(animation.emptyTrack(nFrames)) nJoints = len(jointsData) nFrames = len(jointsData[0]) # Interweave joints animation data, per frame with joints in breadth-first order animData = np.hstack(jointsData).reshape(nJoints * nFrames, 4, 4) framerate = 1.0 / self.frameTime return animation.AnimationTrack(name, animData, nFrames, framerate)
def createAnimationTrack(self, jointsOrder = None, name="BVHMotion"): """ Create an animation track from the motion stored in this BHV file. """ if jointsOrder == None: jointsData = [joint.matrixPoses for joint in self.getJoints() if not joint.isEndConnector()] # We leave out end effectors as they should not have animation data else: nFrames = self.frameCount import re # Remove the tail from duplicate bone names for idx,jName in enumerate(jointsOrder): # Joint mappings can contain a rotation compensation if isinstance(jName, tuple): jName, _ = jName if not jName: continue r = re.search("(.*)_\d+$",jName) if r: jointsOrder[idx] = r.group(1) jointsData = [] for jointName in jointsOrder: if isinstance(jointName, tuple): jointName, angle = jointName else: angle = 0.0 if jointName: poseMats = self.getJointByCanonicalName(jointName).matrixPoses.copy() if isinstance(angle, float): if angle != 0.0: # Rotate around global Z axis rot = tm.rotation_matrix(-angle*D, [0,0,1]) # Roll around global Y axis (this is a limitation) roll = tm.rotation_matrix(angle*D, [0,1,0]) for i in range(nFrames): # TODO make into numpy loop poseMats[i] = np.dot(poseMats[i], rot) poseMats[i] = np.dot(poseMats[i], roll) else: # Compensation (angle) is a transformation matrix # Compensate animation frames for i in range(nFrames): # TODO make into numpy loop poseMats[i] = np.mat(poseMats[i]) * np.mat(angle) #poseMats[i] = np.mat(angle) # Test compensated rest pose jointsData.append(poseMats) else: jointsData.append(animation.emptyTrack(nFrames)) nJoints = len(jointsData) nFrames = len(jointsData[0]) # Interweave joints animation data, per frame with joints in breadth-first order animData = np.hstack(jointsData).reshape(nJoints*nFrames,4,4) framerate = 1.0/self.frameTime return animation.AnimationTrack(name, animData, nFrames, framerate)
def calculateFrames(self): """ Calculate transformation matrices from this joint's (BVH) channel data. """ self.frames = np.asarray(self.frames, dtype=np.float32) nChannels = len(self.channels) nFrames = self.skeleton.frameCount dataLen = nFrames * nChannels if len(self.frames) < dataLen: log.debug("Frame data: %s", self.frames) raise RuntimeError( 'Expected frame data length for joint %s is %s found %s' % (self.getName(), dataLen, len(self.frames))) rotOrder = "" rotAngles = [] rXs = rYs = rZs = None for (chanIdx, channel) in enumerate(self.channels): if channel == "Xposition": rXs = self.frames[chanIdx:dataLen:nChannels] elif channel == "Yposition": if self.skeleton.convertFromZUp: rZs = -self.frames[chanIdx:dataLen:nChannels] else: rYs = self.frames[chanIdx:dataLen:nChannels] elif channel == "Zposition": if self.skeleton.convertFromZUp: rYs = self.frames[chanIdx:dataLen:nChannels] else: rZs = self.frames[chanIdx:dataLen:nChannels] elif channel == "Xrotation": aXs = D * self.frames[chanIdx:dataLen:nChannels] rotOrder = "x" + rotOrder rotAngles.append(aXs) elif channel == "Yrotation": if self.skeleton.convertFromZUp: aYs = -D * self.frames[chanIdx:dataLen:nChannels] rotOrder = "z" + rotOrder else: aYs = D * self.frames[chanIdx:dataLen:nChannels] rotOrder = "y" + rotOrder rotAngles.append(aYs) elif channel == "Zrotation": aZs = D * self.frames[chanIdx:dataLen:nChannels] if self.skeleton.convertFromZUp: rotOrder = "y" + rotOrder else: rotOrder = "z" + rotOrder rotAngles.append(aZs) rotOrder = "s" + rotOrder self.rotOrder = rotOrder # Calculate pose matrix for each animation frame self.matrixPoses = animation.emptyTrack(nFrames) # Add rotations to pose matrices if len(rotAngles) > 0 and len(rotAngles) < 3: # TODO allow partial rotation channels too? pass elif len(rotAngles) >= 3: for frameIdx in range(nFrames): self.matrixPoses[frameIdx, :3, :3] = tm.euler_matrix( rotAngles[2][frameIdx], rotAngles[1][frameIdx], rotAngles[0][frameIdx], axes=rotOrder)[:3, :3] # TODO eliminate loop with numpy? ''' for rotAngle in rotAngles: self.matrixPoses[:] = tm.euler_matrix(rotAngle[2], rotAngle[1], rotAngle[0], axes=rotOrder)) # unfortunately tm.euler_matrix is not a np ufunc ''' # Add translations to pose matrices # Allow partial transformation channels too allowTranslation = self.skeleton.allowTranslation if allowTranslation == "all": poseTranslate = True elif allowTranslation == "onlyroot": poseTranslate = (self.parent is None) else: poseTranslate = False if poseTranslate and (rXs is not None or rYs is not None or rZs is not None): if rXs is None: rXs = np.zeros(nFrames, dtype=np.float32) if rYs is None: rYs = np.zeros(nFrames, dtype=np.float32) if rZs is None: rZs = np.zeros(nFrames, dtype=np.float32) self.matrixPoses[:, :3, 3] = np.column_stack([rXs, rYs, rZs])[:, :]
def createAnimationTrack(self, skel=None, name=None): """ Create an animation track from the motion stored in this BHV file. """ def _bvhJointName(boneName): # Remove the tail from duplicate bone names (added by the BVH parser) import re if not boneName: return boneName r = re.search("(.*)_\d+$", boneName) if r: return r.group(1) return boneName def _createAnimation(jointsData, name, frameTime, nFrames): nJoints = len(jointsData) #nFrames = len(jointsData[0]) # Interweave joints animation data, per frame with joints in breadth-first order animData = np.hstack(jointsData).reshape(nJoints * nFrames, 3, 4) framerate = 1.0 / frameTime return animation.AnimationTrack(name, animData, nFrames, framerate) if name is None: name = self.name if skel is None: jointsData = [ joint.matrixPoses for joint in self.getJoints() if not joint.isEndConnector() ] # We leave out end effectors as they should not have animation data return _createAnimation(jointsData, name, self.frameTime, self.frameCount) elif isinstance(skel, list): # skel parameter is a list of joint or bone names jointsOrder = skel jointsData = [] for jointName in jointsOrder: jointName = _bvhJointName(jointName) if jointName and self.getJointByCanonicalName( jointName) is not None: poseMats = self.getJointByCanonicalName( jointName).matrixPoses.copy() jointsData.append(poseMats) else: jointsData.append(animation.emptyTrack(self.frameCount)) return _createAnimation(jointsData, name, self.frameTime, self.frameCount) else: # skel parameter is a Skeleton jointsData = [] for bone in skel.getBones(): if len(bone.reference_bones) > 0: # Combine the rotations of reference bones to influence this bone # TODO combining poses like this does not work, works with one reference bone only bvhJoints = [] for bonename in bone.reference_bones: jointname = _bvhJointName(bonename) joint = self.getJointByCanonicalName(jointname) if joint: bvhJoints.append(joint) if len(bvhJoints) == 0: poseMats = animation.emptyTrack(self.frameCount) elif len(bvhJoints) == 1: poseMats = bvhJoints[0].matrixPoses.copy() else: # len(bvhJoints) >= 2: # Combine the rotations using quaternions to simplify math and normalizing (rotations only) poseMats = animation.emptyTrack(self.frameCount) m = np.identity(4, dtype=np.float32) for f_idx in range(self.frameCount): m[:3, :4] = bvhJoints[0].matrixPoses[f_idx] q1 = tm.quaternion_from_matrix(m, True) m[:3, :4] = bvhJoints[1].matrixPoses[f_idx] q2 = tm.quaternion_from_matrix(m, True) quat = tm.quaternion_multiply(q2, q1) for bvhJoint in bvhJoints[2:]: m[:3, :4] = bvhJoint.matrixPoses[f_idx] q = tm.quaternion_from_matrix(m, True) quat = tm.quaternion_multiply(q, quat) poseMats[f_idx] = tm.quaternion_matrix( quat)[:3, :4] jointsData.append(poseMats) else: # Map bone to joint by bone name jointName = _bvhJointName(bone.name) joint = self.getJointByCanonicalName(jointName) if joint: jointsData.append(joint.matrixPoses.copy()) else: jointsData.append(animation.emptyTrack( self.frameCount)) return _createAnimation(jointsData, name, self.frameTime, self.frameCount)
def calculateFrames(self): """ Calculate transformation matrices from this joint's (BVH) channel data. """ self.frames = np.asarray(self.frames, dtype=np.float32) nChannels = len(self.channels) nFrames = self.skeleton.frameCount dataLen = nFrames * nChannels if len(self.frames) < dataLen: log.debug("Frame data: %s", self.frames) raise RuntimeError('Expected frame data length for joint %s is %s found %s' % ( self.getName(), dataLen, len(self.frames))) rotOrder = "" rotAngles = [] rXs = rYs = rZs = None for (chanIdx, channel) in enumerate(self.channels): if channel == "Xposition": rXs = self.frames[chanIdx:dataLen:nChannels] elif channel == "Yposition": rYs = self.frames[chanIdx:dataLen:nChannels] elif channel == "Zposition": rZs = self.frames[chanIdx:dataLen:nChannels] elif channel == "Xrotation": aXs = D*self.frames[chanIdx:dataLen:nChannels] rotOrder = "x" + rotOrder rotAngles.append(aXs) elif channel == "Yrotation": if self.skeleton.convertFromZUp: aYs = -D*self.frames[chanIdx:dataLen:nChannels] rotOrder = "z" + rotOrder else: aYs = D*self.frames[chanIdx:dataLen:nChannels] rotOrder = "y" + rotOrder rotAngles.append(aYs) elif channel == "Zrotation": aZs = D*self.frames[chanIdx:dataLen:nChannels] if self.skeleton.convertFromZUp: rotOrder = "y" + rotOrder else: rotOrder = "z" + rotOrder rotAngles.append(aZs) rotOrder = "s"+ rotOrder self.rotOrder = rotOrder # Calculate pose matrix for each animation frame self.matrixPoses = animation.emptyTrack(nFrames) # Add rotations to pose matrices if len(rotAngles) > 0 and len(rotAngles) < 3: # TODO allow partial rotation channels too? pass elif len(rotAngles) >= 3: for frameIdx in range(nFrames): self.matrixPoses[frameIdx,:3,:3] = tm.euler_matrix(rotAngles[2][frameIdx], rotAngles[1][frameIdx], rotAngles[0][frameIdx], axes=rotOrder)[:3,:3] # TODO eliminate loop with numpy? ''' for rotAngle in rotAngles: self.matrixPoses[:] = tm.euler_matrix(rotAngle[2], rotAngle[1], rotAngle[0], axes=rotOrder)) # unfortunately tm.euler_matrix is not a np ufunc ''' # Add translations to pose matrices # Allow partial transformation channels too if rXs != None or rYs != None or rZs != None: if rXs == None: rXs = np.zeros(nFrames, dtype=np.float32) if rYs == None: rYs = np.zeros(nFrames, dtype=np.float32) if rZs == None: rZs = np.zeros(nFrames, dtype=np.float32) self.matrixPoses[:,:3,3] = np.column_stack([rXs,rYs,rZs])[:,:]
def createAnimationTrack(self, skel=None, name=None): """ Create an animation track from the motion stored in this BHV file. """ def _bvhJointName(boneName): # Remove the tail from duplicate bone names (added by the BVH parser) import re if not boneName: return boneName r = re.search("(.*)_\d+$", boneName) if r: return r.group(1) return boneName def _createAnimation(jointsData, name, frameTime, nFrames): nJoints = len(jointsData) #nFrames = len(jointsData[0]) # Interweave joints animation data, per frame with joints in breadth-first order animData = np.hstack(jointsData).reshape(nJoints*nFrames,3,4) framerate = 1.0/frameTime return animation.AnimationTrack(name, animData, nFrames, framerate) if name is None: name = self.name if skel is None: jointsData = [joint.matrixPoses for joint in self.getJoints() if not joint.isEndConnector()] # We leave out end effectors as they should not have animation data return _createAnimation(jointsData, name, self.frameTime, self.frameCount) elif isinstance(skel, list): # skel parameter is a list of joint or bone names jointsOrder = skel jointsData = [] for jointName in jointsOrder: jointName = _bvhJointName(jointName) if jointName and self.getJointByCanonicalName(jointName) is not None: poseMats = self.getJointByCanonicalName(jointName).matrixPoses.copy() jointsData.append(poseMats) else: jointsData.append(animation.emptyTrack(self.frameCount)) return _createAnimation(jointsData, name, self.frameTime, self.frameCount) else: # skel parameter is a Skeleton jointsData = [] for bone in skel.getBones(): if len(bone.reference_bones) > 0: # Combine the rotations of reference bones to influence this bone bvhJoints = [] for bonename in bone.reference_bones: jointname = _bvhJointName(bonename) joint = self.getJointByCanonicalName(jointname) if joint: bvhJoints.append(joint) if len(bvhJoints) == 0: poseMats = animation.emptyTrack(self.frameCount) elif len(bvhJoints) == 1: poseMats = bvhJoints[0].matrixPoses.copy() else: # len(bvhJoints) >= 2: # Combine the rotations using quaternions to simplify math and normalizing (rotations only) poseMats = animation.emptyTrack(self.frameCount) m = np.identity(4, dtype=np.float32) for f_idx in xrange(self.frameCount): m[:3,:4] = bvhJoints[0].matrixPoses[f_idx] q1 = tm.quaternion_from_matrix(m, True) m[:3,:4] = bvhJoints[1].matrixPoses[f_idx] q2 = tm.quaternion_from_matrix(m, True) quat = tm.quaternion_multiply(q2, q1) for bvhJoint in bvhJoints[2:]: m[:3,:4] = bvhJoint.matrixPoses[f_idx] q = tm.quaternion_from_matrix(m, True) quat = tm.quaternion_multiply(q, quat) poseMats[f_idx] = tm.quaternion_matrix( quat )[:3,:4] jointsData.append(poseMats) else: # Map bone to joint by bone name jointName = _bvhJointName(bone.name) joint = self.getJointByCanonicalName(jointName) if joint: jointsData.append( joint.matrixPoses.copy() ) else: jointsData.append(animation.emptyTrack(self.frameCount)) return _createAnimation(jointsData, name, self.frameTime, self.frameCount)