def simbone_bake(ob, pose_bone, edit_bone, scene): frames, frame_step = get_scene_frames(scene) matrices = get_matrices(ob, pose_bone, edit_bone, frames) end_mats = get_matrices_single_bone(ob, pose_bone, edit_bone, frames) # Main lists. positions = [ mat.decompose()[0] * scene.simboneworld.spaceScale for mat in matrices ] orientations = [(matrices[i] @ end_mats[i].inverted()).decompose()[1] for i in range(len(end_mats))] velocities = [(positions[i] - positions[max(0, i - 1)]) / frame_step for i in range(len(positions))] accelerations = [(velocities[i] - velocities[max(0, i - 1)]) / frame_step for i in range(len(velocities))] gravity = get_gravity(scene) custom_force = pose_bone.simbone.custom_force.copy() up_quat = Euler((pose_bone.simbone.up_offset - 90, 0, 0)).to_quaternion() start_dir = bone_quat_to_dir(matrices[0].decompose()[1]) # Setup pendulum values. pen = Pendulum() pen.l = edit_bone.length * scene.simboneworld.spaceScale pen.m = pose_bone.simbone.m pen.set_coords(start_dir) pen.c_a = pose_bone.simbone.c_a pen.c_d = pose_bone.simbone.c_d datapath = 'pose.bones["' + pose_bone.name + '"].rotation_quaternion' pose_bone.rotation_mode = 'QUATERNION' pose_bone.rotation_quaternion = end_mats[0].decompose()[1] pose_bone.keyframe_insert(data_path='rotation_quaternion', frame=frames[0]) fcurves = [ ob.animation_data.action.fcurves.find(datapath, index=i) for i in range(4) ] for i in range(1, len(matrices)): matrix = matrices[i] frame = frames[i] g = gravity.copy() f = custom_force.copy() f.rotate(orientations[i]) pen.w = scene.simboneworld.wind - velocities[i] pen.f = g + f - accelerations[i] pen.do_steps(frame_step * scene.simboneworld.timeScale, 1) direction = Vector(pen.get_coords()) direction.rotate(orientations[i].inverted()) direction.rotate(up_quat.inverted()) orient = direction.to_track_quat('Y', 'Z') orient.rotate(up_quat) for i in range(4): fcurves[i].keyframe_points.insert(frame, orient[i])
def execute(self, context): # Cursor matrix cmat = self.cmat.copy() # Local rotation matrix mat = Euler((radians(angle) for angle in self.xyz)).to_matrix() # Multiply with inverse local rotation matrix new_mat = cmat @ mat.inverted() context.scene.cursor.rotation_quaternion = new_mat.to_quaternion() return {'FINISHED'}
def apply_animation(bones, arm_obj, jntframes, name=None): """apply keyframes from pseudobones to real, armature bones""" if name: arm_obj.animation_data.action = bpy.data.actions.new(name + '_action') else: arm_obj.animation_data.action = bpy.data.actions.new(arm_obj.name+'_action') bpy.context.scene.frame_current = 0 # warning: here, the `name` var changes meaning for com in bones: name = com.name.fget() arm_obj.data.bones[name].use_inherit_scale = False # scale can be applied posebone = arm_obj.pose.bones[name] posebone.rotation_mode = "XZY" # remember, coords are flipped bpy.context.scene.frame_current = 0 # this keyframe is needed, overwritten anyways # also it is always at 1 because this function is called once per action posebone.keyframe_insert('location') posebone.keyframe_insert('rotation_euler') posebone.keyframe_insert('scale') fcurves = arm_obj.animation_data.action.fcurves data = {} for curve in fcurves: # create data in dicts ({bonename:{datatype:[0,1,2]...}...}) try: bonename, datatype = finder.match(curve.data_path).groups() except TypeError: # cannit unpack None: this fsurve is not interesting continue bonedict = common.dict_get_set(data, bonename, {}) datadict = common.dict_get_set(bonedict, datatype, [None, None, None]) datadict[curve.array_index] = curve # create keyframes, with tengents for com in bones: name = com.name.fget() bonedict = data[name] posebone = arm_obj.pose.bones[name] bpy.context.scene.frame_current = 0 posebone.keyframe_insert('location') posebone.keyframe_insert('rotation_euler') posebone.keyframe_insert('scale') every_frame = list(com.frames.times.keys()) every_frame.sort() refpos = com.jnt_frame if type(com.parent.fget()) is not Pseudobone: com.rotmatrix = Matrix.Identity(4) com.parentrot = Matrix.Identity(4) else: com.rotmatrix = com.parent.fget().rotmatrix com.parentrot = com.parent.fget().rotmatrix tempmat = Euler((refpos.rx, refpos.ry, refpos.rz), 'XYZ').to_matrix().to_4x4() com.rotmatrix *= tempmat cancel_ref_rot = tempmat.inverted() for frame in every_frame: bpy.context.scene.frame_current = frame # flip y and z if com.frames.times[frame][0]: vct, tgL, tgR = get_pos_vct(com, frame) if not math.isnan(vct.x): posebone.location[0] = vct.x co = bonedict['location'][0].keyframe_points[-1].co bonedict['location'][0].keyframe_points[-1].handle_left = co+Vector((-1, -tgL.x)) bonedict['location'][0].keyframe_points[-1].handle_right = co+Vector((1, tgR.x)) posebone.keyframe_insert('location', 0) # fixed: add frame to keyframes AFTER setting the right value to it. so conter-intuitive. if not math.isnan(vct.z): posebone.location[1] = -vct.z co = bonedict['location'][1].keyframe_points[-1].co bonedict['location'][1].keyframe_points[-1].handle_left = co + Vector((-1, tgL.z)) bonedict['location'][1].keyframe_points[-1].handle_right = co + Vector((1, -tgR.z)) posebone.keyframe_insert('location', 1) if not math.isnan(vct.y): posebone.location[2] = vct.y co = bonedict['location'][2].keyframe_points[-1].co bonedict['location'][2].keyframe_points[-1].handle_left = co + Vector((-1, -tgL.y)) bonedict['location'][2].keyframe_points[-1].handle_right = co + Vector((1, tgR.y)) posebone.keyframe_insert('location', 2) if com.frames.times[frame][1]: vct, tgL, tgR = get_rot_vct(com, frame) if not math.isnan(vct.x): posebone.rotation_euler[0] = vct.x co = bonedict['rotation_euler'][0].keyframe_points[-1].co bonedict['rotation_euler'][0].keyframe_points[-1].handle_left = co + Vector((-1, -tgL.x)) bonedict['rotation_euler'][0].keyframe_points[-1].handle_right = co + Vector((1, tgR.x)) posebone.keyframe_insert('rotation_euler', 0) if not math.isnan(vct.z): posebone.rotation_euler[1] = -vct.z co = bonedict['rotation_euler'][1].keyframe_points[-1].co bonedict['rotation_euler'][1].keyframe_points[-1].handle_left = co + Vector((-1, tgL.z)) bonedict['rotation_euler'][1].keyframe_points[-1].handle_right = co + Vector((1, -tgR.z)) posebone.keyframe_insert('rotation_euler', 1) if not math.isnan(vct.y): posebone.rotation_euler[2] = vct.y co = bonedict['rotation_euler'][2].keyframe_points[-1].co bonedict['rotation_euler'][2].keyframe_points[-1].handle_left = co + Vector((-1, -tgL.y)) bonedict['rotation_euler'][2].keyframe_points[-1].handle_right = co + Vector((1, tgR.y)) posebone.keyframe_insert('rotation_euler', 2) if com.frames.times[frame][2]: vct, tgL, tgR = get_sc_vct(com, frame) if not math.isnan(vct.x): posebone.scale[0] = vct.x co = bonedict['scale'][0].keyframe_points[-1].co bonedict['scale'][0].keyframe_points[-1].handle_left = co + Vector((-1, -tgL.x)) bonedict['scale'][0].keyframe_points[-1].handle_right = co + Vector((1, tgR.x)) posebone.keyframe_insert('scale', 0) if not math.isnan(vct.z): posebone.scale[1] = vct.z co = bonedict['scale'][1].keyframe_points[-1].co bonedict['scale'][1].keyframe_points[-1].handle_left = co + Vector((-1, tgL.z)) bonedict['scale'][1].keyframe_points[-1].handle_right = co + Vector((1, -tgR.z)) posebone.keyframe_insert('scale', 1) if not math.isnan(vct.y): posebone.scale[2] = vct.y co = bonedict['scale'][2].keyframe_points[-1].co bonedict['scale'][2].keyframe_points[-1].handle_left = co + Vector((-1, -tgL.y)) bonedict['scale'][2].keyframe_points[-1].handle_right = co + Vector((1, tgR.y)) posebone.keyframe_insert('scale', 2) return arm_obj.animation_data.action