4
$\begingroup$

I have an armature of animated bones and I want to rotate the main bone by 90 degrees in edit mode so that that particular bone has the right orientation when exporting the animation for the source engine (I accidentally animated it with the wrong rotation).

My animations are already finished, so when I rotate the bone in edit mode now it messes up the animation. (The bone is moved away from its original position and moves in the wrong direction during the animation.)

How do I fix this?

This is what the problem looks like: Bone is rotated is edit mode

Here's one of the .blend files (not rotated): idle.blend

$\endgroup$
  • $\begingroup$ Try to roll the bone 180 degrees and then in graph editor depending on your bone rotation orientation, mirror one of the rotation curves while cursor is located at 0. You will have to offset the location curves of the bone too because pivot point of the bone is not in the center. $\endgroup$ – Denis Apr 26 '15 at 22:03
  • $\begingroup$ Sorry but I'm not very familiar with the graph editor (I'm pretty new to blender), so how exactly do you do that? $\endgroup$ – DonutVikingChap Apr 26 '15 at 22:12
  • $\begingroup$ On the top of your Blender window change Default layout to Animation, there you will see Graph Editor window, and while your bone selected in pose mode you can edit the translation curves. $\endgroup$ – Denis Apr 26 '15 at 22:18
  • $\begingroup$ Can you attach the blend file? $\endgroup$ – Denis Apr 26 '15 at 22:33
  • $\begingroup$ Sure, just give me a sec. EDIT: there. $\endgroup$ – DonutVikingChap Apr 26 '15 at 22:37
1
$\begingroup$

Here's a function I wrote that lets you rotate a bone in edit mode and automatically corrects all animations so they maintain the same orientation:

def reorient_bone(operator, context, fixed_items, layers=(), bone_name="Bip0", location=mathutils.Vector((0,0,1)), rotation=mathutils.Euler((0,0,1)) ):
    qrn = rotation.to_quaternion().conjugated()
    qe = rotation.to_quaternion()
    #when no object exists, or when we are in edit mode when script is run
    for ob in bpy.context.scene.objects:
        if type(ob.data) ==  bpy.types.Armature:
            bpy.context.scene.objects.active = ob
            bpy.ops.object.mode_set(mode='EDIT')
            for bone in ob.data.edit_bones:
                if bone.name == bone_name:
                    l =  mathutils.Vector(bone.head)
                    m =  rotation.to_matrix() * bone.matrix.to_3x3()
                    bone.head = mathutils.Vector((0,0,0))
                    bone.tail = mathutils.Vector((0,1,0))
                    bone.roll = 0
                    bone.transform(m)
                    bone.translate(l)
            bpy.ops.object.mode_set(mode='POSE')

    for action in bpy.data.actions:
        for group in action.groups:
            if group.name == bone_name:
                #rotate the translation so the movement of the bone remains identical
                for t in ("location", "quaternion"):
                    curves = [fcurve for fcurve in group.channels if fcurve.data_path.endswith(t)]
                    if curves:
                        num_keys = len(curves[0].keyframe_points)
                        for i in range(0, num_keys):
                            frame = curves[0].keyframe_points[i].co[0]
                            key = [fcurve.keyframe_points[i].co[1] for fcurve in curves]
                            if len(curves) == 3:
                                key =  qrn * mathutils.Vector(key)
                            else:
                                #arbitrary rotations keeping the worldspace character of the rotation
                                if fixed_items == "0":
                                    q = mathutils.Quaternion(key)
                                    v, a = q.to_axis_angle()
                                    v =  qrn * mathutils.Vector(v)
                                    key = mathutils.Quaternion(v, a)

                                #for the other case - restore rotation around rest bone change
                                if fixed_items == "1":
                                    key = mathutils.Quaternion(key) * qe
                            for a in range(0,len(curves)):
                                curves[a].keyframe_points[i].co[1] = key[a]
                        for fcurve in curves:   
                            fcurve.update()
    #call the tangent function
    loop_fcurve_tangents()
    return {'FINISHED'}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.